Declarations
Declarations introduce (or re-introduce) names into the C++ program. Each kind of entity is declared differently. Definitions are declarations that are sufficient to use the entity identified by the name.
A declaration is one of the following:
- Function declaration
- Template declaration
- Explicit template instantiation
- Explicit template specialization
- Namespace definition
- Linkage specification
-  Attribute declaration (attr ;) (since C++11)
-  Empty declaration (;)
- Block declaration (a declaration that can appear inside a block), which, in turn, can be one of the following:
- asm definition
- type alias declaration
- namespace alias definition
- using declaration
- using directive
- static_assert declaration
- opaque enum declaration
- simple declaration
 
Simple declaration is a statement that introduces, creates, and optionally initializes one or several identifiers, typically variables.
| attr(optional) decl-specifier-seq(optional) init-declarator-list(optional) ; | (1) | ||||||||
| attr(C++11) | - | optional sequence of any number of attributes | 
| decl-specifier-seq | - | sequence of type specifiers including the type name. It is only optional in the declarations of constructors, destructors, and user-defined type conversion functions | 
| init-declarator-list | - | comma-separated list of declarators with optional initializers. Init-declarator-list is optional when declaring a named class/struct/union or a named enumeration | 
| Contents | 
[edit] Specifiers
decl-specifier-seq is a sequence of the following whitespace-separated specifiers:
- typedef specifier. If present, the entire declaration is a typedef declaration and each declarator introduces a new type name, not an object or a function.
- function specifier (inline, virtual, explicit), only allowed in function declarations
- friend specifier, allowed in class and function declarations.
- constexpr specifier, only allowed in variable definitions, function and function template declarations, and the declaration of static data members of literal type.
-  storage class specifier (register, static, thread_local (since C++11), extern, mutable). Only one storage class specifier is allowed, except that thread_localmay appear together withexternorstatic.
- type-specifier-seq, i.e. a sequence of type specifiers, which can be any one of the following:
- class specifier
- enum specifier
- simple type specifier
 
| (since C++11) | 
- previously declared class name (optionally qualified)
- previously declared enum name (optionally qualified)
- previously declared typedef-name or type alias (since C++11) (optionally qualified)
- template name with template arguments (optionally qualified, optionally using template disambiguator)
 
 - the keyword class, struct, or union, followed by the identifier (optionally qualified), previously defined as the name of a class, struct, or union.
- the keyword class, struct, or union, followed by template name with template arguments (optionally qualified, optionally using template disambiguator), previously defined as the name of a class template.
- the keyword enum followed by the identifier (optionally qualified), previously declared as the name of an enumeration.
 
 
- only one type specifier is allowed in a decl-specifier-seq, with the following exceptions:
- - constcan be combined with any type specifier except itself.
- - volatilecan be combined with any type specifier except itself.
- - signedorunsignedcan be combined withchar,long,short, orint.
- - shortorlongcan be combined withint.
- - longcan be combined withdouble.
| 
 | (since C++11) | 
Attributes may appear in decl-specifier-seq, in which case they apply to the type determined by the preceding specifiers.
| The only specifier that is allowed to appear twice in a decl-specifier-seq is  | (since C++17) | 
[edit] Declarators
init-declarator-seq is a comma-separated sequence of one or more init-declarators, which have the following syntax:
| declarator initializer(optional) | (1) | ||||||||
| declarator | - | the declarator | 
| initializer | - | optional initializer (except where required, such as when initializing references or const objects). See Initialization for details. | 
Each init-declaractor in a init-declarator sequence S D1, D2, D3; is processed as if it were a standalone declaration with the same specifiers: S D1; S D2; S D3;.
Each declarator introduces exactly one object, function, or (for typedef declarations) type alias, whose type is provided by decl-specifier-seq and optionally modified by operators such as & (reference to) or [] (array of) or () (function returning) in the declarator. These operators can be applied recursively, as shown below.
A declarator is one of the following:
| name attr(optional) | (1) | ||||||||
| qualified-id attr(optional) | (2) | ||||||||
| ...identifier attr(optional) | (3) | (since C++11) | |||||||
| *attr(optional) cv(optional) declarator | (4) | ||||||||
| nested-name-specifier *attr(optional) cv(optional) declarator | (5) | ||||||||
| &attr(optional) declarator | (6) | ||||||||
| &&attr(optional) declarator | (7) | (since C++11) | |||||||
| noptr-declarator [constexpr(optional)]attr(optional) | (8) | ||||||||
| noptr-declarator (parameter-list)cv(optional) ref(optional) except(optional) attr(optional) | (9) | ||||||||
D as a pointer to the type determined by decl-specifier-seq S.D as a pointer to member of C of type determined by decl-specifier-seq S. nested-name-specifier is a sequence of names and scope resolution operators ::D with type lvalue reference to the type determined by decl-specifier-seq S.D with type rvalue reference to the type determined by decl-specifier-seq S.In all cases, attr is an optional sequence of attributes. When appearing immediately after the identifier, it applies to the object being declared.
cv is a sequence of const and volatile qualifiers, where either qualifier may appear at most once in the sequence.
| This section is incomplete Reason: explain declaration name hiding rules; how a variable/function declaration hides a class (but not a typedef) with the same name | 
[edit] Notes
When a block declaration appears inside a block, and an identifier introduced by a declaration was previously declared in an outer block, the outer declaration is hidden for the remainder of the block.
If a declaration introduces a variable with automatic storage duration, it is initialized when its declaration statement is executed. All automatic variables declared in a block are destroyed on exit from the block (regardless how the block is exited: via exception, goto, or by reaching its end), in order opposite to their order of initialization.
[edit] Examples
class C { std::string member; // decl-specifier-seq is "std::string" // declarator is "member" } obj, *pObj(&obj); // decl-specifier-seq is "class C { std::string member; }" // declarator "obj" defines an object of type C // declarator "*pObj(&obj)" declares and initializes a pointer to C int a = 1, *p = NULL, f(), (*pf)(double); // decl-specifier-seq is int // declarator a=1 defines and initializes a variable of type int // declarator *p=NULL defines and initializes a variable of type int* // declarator (f)() declares (but doesn't define) // a function taking no arguments and returning int // declarator (*pf)(double) defines a pointer to function // taking double and returning int int (*(*foo)(double))[3] = NULL; // decl-specifier-seq is int // 1. declarator "(*(*foo)(double))[3]" is an array declarator: // the type declared is "/nested declarator/ array of 3 int" // 2. the nested declarator is "*(*foo)(double))", which is a pointer declarator // the type declared is "/nested declarator/ pointer to array of 3 int" // 3. the nested declarator is "(*foo)(double)", which is a function declarator // the type declared is "/nested declarator/ function taking double and returning // pointer to array of 3 int" // 4. the nested declarator is "(*foo)" which is a (parenthesized, as required by // function declarator syntax) pointer declarator. // the type declared is "/nested declarator/ pointer to function taking double // and returning pointer to array of 3 int" // 5. the nested declarator is "foo", which is an identifier. // The declaration declares the object foo of type "pointer to function taking double // and returning pointer to array of 3 int" // The initializer "= NULL" provides the initial value of this pointer.
 


