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 definition
 - Template declaration (including Partial template specialization)
 - Explicit template instantiation
 - Explicit template specialization
 - Namespace definition
 - Linkage specification
 -  Attribute declaration (attr 
;) (since C++11) -  Empty declaration (
;) (since C++11) - A function declaration without a decl-specifier-seq:
 
 attr(optional) declarator ;  |  
| attr (since C++11) | - | sequence of any number of attributes | 
| declarator | - | A function declarator. | 
- Block declaration (a declaration that can appear inside a block), which, in turn, can be one of the following:
 - asm definition
 - type alias declaration (since C++11)
 - namespace alias definition
 - using declaration
 - using directive
 - static_assert declaration (since C++11)
 - opaque enum declaration (since C++11)
 - simple declaration
 
Simple declaration
A simple declaration is a statement that introduces, creates, and optionally initializes one or several identifiers, typically variables.
 decl-specifier-seq init-declarator-list(optional) ;  |  (1) | |
 attr decl-specifier-seq init-declarator-list;  |  (2) | 
| attr (since C++11) | - | sequence of any number of attributes | 
| decl-specifier-seq | - | sequence of specifiers (see below). | 
| 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 | 
A structured binding declaration is also a simple declaration. (since C++17).
Specifiers
Declaration specifiers (decl-specifier-seq) is a sequence of the following whitespace-separated specifiers, in any order:
-  the 
typedefspecifier. If present, the entire declaration is a typedef declaration and each declarator introduces a new type name, not an object or a function. -  function specifiers (
inline,virtual,explicit), only allowed in function declarations 
 
  |  (since C++17) | 
-  the 
friendspecifier, allowed in class and function declarations. 
 
  |  (since C++11) | 
 
  |  (since C++20) | 
-  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 specifiers (type-specifier-seq), a sequence of specifiers that names a type. The type of every entity introduced by the declaration is this type, optionally modified by the declarator (see below). This sequence of specifiers is also used by type-id. Only the following specifiers are part of type-specifier-seq, in any order:
 - 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)
 
 
  |  (since C++17) | 
- 
- elaborated type specifier
 - 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.
 - typename specifier
 - cv qualifier
 
 - 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. 
 - long can be combined with long.   |  (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) | 
Declarators
init-declarator-list is a comma-separated sequence of one or more init-declarators, which have the following syntax:
| declarator initializer(optional) | (1) | |
| declarator requires-clause | (2) | (since C++20) | 
| declarator | - | the declarator | 
| initializer | - | optional initializer (except where required, such as when initializing references or const objects). See Initialization for details. | 
| requires-clause(C++20) | - | a requires-clause, which adds a constraint to a function declaration | 
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, reference, 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:
| unqualified-id 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) | 
S * D; declares D as a pointer to the type determined by decl-specifier-seq S.S C::* D; declares 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 ::
S & D; declares D as an lvalue reference to the type determined by decl-specifier-seq S.S && D; declares D as an 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.
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.
Examples
#include <string>
 
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 = nullptr, f(), (*pf)(double);
// decl-specifier-seq is int
// declarator a = 1 defines and initializes a variable of type int
// declarator *p = nullptr 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] = nullptr;
// 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 "= nullptr" provides the initial value of this pointer.
    © cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
    http://en.cppreference.com/w/cpp/language/declarations