Namespaces
Variants

Declarations

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Déclarations sont la manière dont les noms sont introduits (ou réintroduits) dans le programme C++. Toutes les déclarations ne déclarent pas réellement quelque chose, et chaque type d'entité est déclaré différemment. Définitions sont des déclarations qui sont suffisantes pour utiliser l'entité identifiée par le nom.

Une déclaration est l'une des suivantes :

  • Déclaration d'attribut ( attr ; )
(depuis C++11)
  • Déclaration vide ( ; )
  • Une déclaration de fonction sans decl-specifier-seq :
attr  (facultatif) déclarateur ;
attr - (since C++11) séquence d'un nombre quelconque d' attributs
declarator - un déclarateur de fonction
Cette déclaration doit déclarer un constructeur, un destructeur, ou une fonction de conversion conversion function . Elle ne peut être utilisée que comme partie d'une template declaration , explicit specialization , ou explicit instantiation.
  • block-declaration (une déclaration qui peut apparaître à l'intérieur d'un bloc ), qui, à son tour, peut être l'une des suivantes :
(depuis C++11)
(depuis C++20)
(depuis C++11)
  • déclaration simple

Table des matières

Déclaration simple

Une simple déclaration est une instruction qui introduit, crée et optionnellement initialise un ou plusieurs identifiants, généralement des variables.

decl-specifier-seq init-declarator-list  (optionnel) ; (1)
attr decl-specifier-seq init-declarator-list ; (2) (depuis C++11)
decl-specifier-seq - séquence de spécificateurs
init-declarator-list - liste séparée par des virgules de init-declarator s (voir ci-dessous)
attr - séquence d'un nombre quelconque d' attributs


init-declarator-list ne peut être omis que lors de la déclaration d'une classe nommée ou d'une énumération nommée.

Une déclaration de liaison structurée est également une déclaration simple.

(depuis C++17)


La syntaxe de init-declarator est définie comme suit :

declarator initializer (1)
declarator requires-clause  (optionnel) contract-specs  (optionnel) (2)
1) Un déclarateur avec un initialiseur.
2) Un déclarateur sans initialiseur.
declarator - un declarator
initializer - un initializer
requires-clause - (since C++20) une requires clause
contract-specs - (since C++26) une liste de function contract specifiers


requires-clause ne peut apparaître que si declarator déclare une fonction template .

(depuis C++20)

contract-specs ne peut apparaître que si declarator déclare une fonction ou un template de fonction.

(depuis C++26)

Spécificateurs

Spécificateurs de déclaration ( decl-specifier-seq ) est une séquence des spécificateurs suivants, séparés par des espaces, dans n'importe quel ordre :

  • le spécificateur inline est également autorisé sur les déclarations de variables.
(depuis C++17)
  • le friend spécificateur, autorisé dans les déclarations de classes et de fonctions.
  • le spécificateur constexpr , uniquement autorisé dans les définitions de variables, les déclarations de fonctions et de modèles de fonctions, et la déclaration des membres de données statiques de type littéral.
(depuis C++11)
  • le spécificateur consteval , uniquement autorisé dans les déclarations de fonctions et de modèles de fonctions.
  • le spécificateur constinit , uniquement autorisé dans la déclaration d'une variable avec une durée de stockage statique ou thread. Au plus un des spécificateurs constexpr , consteval , et constinit est autorisé à apparaître dans une decl-specifier-seq .
(depuis C++20)
  • spécificateur de classe de stockage ( register , (jusqu'en C++17) static , thread_local , (depuis C++11) extern , mutable ). Un seul spécificateur de classe de stockage est autorisé , sauf que thread_local peut apparaître avec extern ou static (depuis C++11) .
  • Spécificateurs de type ( type-specifier-seq ), une séquence de spécificateurs qui nomme un type. Le type de chaque entité introduite par la déclaration est ce type, optionnellement modifié par le déclarateur (voir ci-dessous). Cette séquence de spécificateurs est également utilisée par type-id . Seuls les spécificateurs suivants font partie de type-specifier-seq , dans n'importe quel ordre :
(depuis C++11)
(depuis C++26)
(depuis C++17)
un seul spécificateur de type est autorisé dans une séquence de spécificateurs de déclaration, avec les exceptions suivantes :
  • const peut être combiné avec n'importe quel spécificateur de type sauf lui-même.
  • volatile peut être combiné avec n'importe quel spécificateur de type sauf lui-même.
  • signed ou unsigned peuvent être combinés avec char , long , short , ou int .
  • short ou long peuvent être combinés avec int .
  • long peut être combiné avec double .
  • long peut être combiné avec long .
(depuis C++11)

Attributs peuvent apparaître dans decl-specifier-seq , auquel cas ils s'appliquent au type déterminé par les spécificateurs précédents.

Les répétitions de tout spécificateur dans une decl-specifier-seq , telles que const static const , ou virtual inline virtual sont des erreurs , sauf que long est autorisé à apparaître deux fois (depuis C++11) .

Déclarateurs

Chaque init-declarator dans une init-declarator-list S D1, D2, D3 ; est traité comme s'il s'agissait d'une déclaration autonome avec les mêmes spécificateurs : S D1 ; S D2 ; S D3 ; .

Chaque déclarateur introduit exactement un objet, référence, fonction ou (pour les déclarations typedef) alias de type, dont le type est fourni par decl-specifier-seq et optionnellement modifié par des opérateurs tels que & (référence vers) ou [ ] (tableau de) ou ( ) (fonction retournant) dans le déclarateur. Ces opérateurs peuvent être appliqués récursivement, comme montré ci-dessous.

Un déclarateur est l'un des éléments suivants :

unqualified-id attr  (optionnel) (1)
qualified-id attr  (optionnel) (2)
... identifier attr  (optionnel) (3) (depuis C++11)
* attr  (optionnel) cv  (optionnel) declarator (4)
nested-name-specifier * attr  (optionnel) cv  (optionnel) declarator (5)
& attr  (optionnel) declarator (6)
&& attr  (optionnel) declarator (7) (depuis C++11)
noptr-declarator [ constant-expression  (optionnel) ] attr  (optionnel) (8)
noptr-declarator ( parameter-list ) cv  (optionnel) ref   (optionnel) except  (optionnel) attr  (optionnel) (9)
( declarator ) (10)
1) Le nom qui est déclaré.
2) Un déclarateur qui utilise un identifiant qualifié ( qualified-id ) définit ou redéclare un membre d'espace de noms ou un membre de classe précédemment déclaré.
3) Parameter pack , n'apparaît que dans les déclarations de paramètres .
4) Déclarateur de pointeur : la déclaration S * D ; déclare D comme un pointeur vers le type déterminé par decl-specifier-seq S .
5) Déclaration de pointeur vers membre : la déclaration S C :: * D ; déclare D comme un pointeur vers membre de C de type déterminé par decl-specifier-seq S . nested-name-specifier est une séquence de noms et d'opérateurs de résolution de portée ::
6) Déclarateur de référence Lvalue : la déclaration S & D ; déclare D comme une référence Lvalue vers le type déterminé par decl-specifier-seq S .
7) Déclarateur de référence à valeur résiduelle : la déclaration S && D ; déclare D comme une référence à valeur résiduelle vers le type déterminé par decl-specifier-seq S .
8) Déclarateur de tableau . noptr-declarator tout déclarateur valide, mais s'il commence par *, &, ou &&, il doit être entouré de parenthèses.
9) Déclarateur de fonction . noptr-declarator tout déclarateur valide, mais s'il commence par *, &, ou &&, il doit être entouré de parenthèses. Il peut se terminer par le type de retour optionnel en suffixe. (depuis C++11)
10) Déclarateur entre parenthèses.

Dans tous les cas, attr est une séquence optionnelle d' attributs . Lorsqu'il apparaît immédiatement après l'identifiant, il s'applique à l'objet étant déclaré.

(since C++11)

cv est une séquence de qualificateurs const et volatile , où chaque qualificateur peut apparaître au plus une fois dans la séquence.

Notes

Lorsqu'une block-declaration apparaît à l'intérieur d'un bloc , et qu'un identifiant introduit par une déclaration a été précédemment déclaré dans un bloc externe, la déclaration externe est masquée pour le reste du bloc.

Si une déclaration introduit une variable avec une durée de stockage automatique, elle est initialisée lorsque son instruction de déclaration est exécutée. Toutes les variables automatiques déclarées dans un bloc sont détruites à la sortie du bloc (peu importe comment le bloc est quitté : via exception , goto , ou en atteignant sa fin), dans l'ordre inverse de leur ordre d'initialisation.

Exemple

Note : cet exemple démontre comment certaines déclarations complexes sont analysées en termes de grammaire du langage. D'autres mnémoniques populaires sont : la règle en spirale , la lecture de l'intérieur vers l'extérieur , et la déclaration reflète l'utilisation . Il existe également un analyseur automatisé sur https://cdecl.org .

#include <type_traits>
struct S
{
    int member;
    // decl-specifier-seq is "int"
    // declarator is "member"
} obj, *pObj(&obj);
// decl-specifier-seq is "struct S { int member; }"
// declarator "obj" declares an object of type S
// declarator "*pObj" declares a pointer to S,
//     and initializer "(&obj)" initializes it
int i = 1, *p = nullptr, f(), (*pf)(double);
// decl-specifier-seq is "int"
// declarator "i" declares a variable of type int,
//     and initializer "= 1" initializes it
// declarator "*p" declares a variable of type int*,
//     and initializer "= nullptr" initializes it
// declarator "f()" declares (but doesn't define)
//     a function taking no arguments and returning int
// declarator "(*pf)(double)" declares a pointer to function
//     taking double and returning int
int (*(*var1)(double))[3] = nullptr;
// decl-specifier-seq is "int"
// declarator is "(*(*var1)(double))[3]"
// initializer is "= nullptr"
// 1. declarator "(*(*var1)(double))[3]" is an array declarator:
//    Type declared is: "(*(*var1)(double))" array of 3 elements
// 2. declarator "(*(*var1)(double))" is a pointer declarator:
//    Type declared is: "(*var1)(double)" pointer to array of 3 elements
// 3. declarator "(*var1)(double)" is a function declarator:
//    Type declared is: "(*var1)" function taking "(double)",
//    returning pointer to array of 3 elements.
// 4. declarator "(*var1)" is a pointer declarator:
//    Type declared is: "var1" pointer to function taking "(double)",
//    returning pointer to array of 3 elements.
// 5. declarator "var1" is an identifier.
// This declaration declares the object var1 of type "pointer to function
// taking double and returning pointer to array of 3 elements of type int"
// The initializer "= nullptr" provides the initial value of this pointer.
// C++11 alternative syntax:
auto (*var2)(double) -> int (*)[3] = nullptr;
// decl-specifier-seq is "auto"
// declarator is "(*var2)(double) -> int (*)[3]"
// initializer is "= nullptr"
// 1. declarator "(*var2)(double) -> int (*)[3]" is a function declarator:
//    Type declared is: "(*var2)" function taking "(double)", returning "int (*)[3]"
// ...
int main()
{
    static_assert(std::is_same_v<decltype(var1), decltype(var2)>);
}

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
CWG 482 C++98 les déclarateurs des redéclarations ne pouvaient pas être qualifiés déclarateurs qualifiés autorisés
CWG 569 C++98 un point-virgule isolé n'était pas une déclaration valide c'est une déclaration vide,
qui n'a aucun effet
CWG 1830 C++98 la répétition d'un spécificateur de fonction dans une decl-specifier-seq était autorisée la répétition est interdite

Voir aussi

Documentation C pour Déclarations