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:
;
) (since C++11) ;
) (since C++11) attr(optional) declarator ; |
attr (since C++11) | - | sequence of any number of attributes |
declarator | - | A function declarator. |
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).
Declaration specifiers (decl-specifier-seq) is a sequence of the following whitespace-separated specifiers, in any order:
| (since C++17) |
thread_local
may appear together with extern
or static
. (since C++11) |
| (since C++17) |
const
can be combined with any type specifier except itself. volatile
can be combined with any type specifier except itself. signed
or unsigned
can be combined with char
, long
, short
, or int
. short
or long
can be combined with int
. long
can be combined with double
. - 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) |
Structured binding declaration
A structured binding declaration introduces all identifiers in the identifier-list as names (called structured bindings) and binds them to subobjects or elements of the object returned by expression, as follows:
E denote type of the expression e (note that E is never a reference type).
int a[2] = {1,2}; auto f() -> int(&)[2] { return a; } auto [x,y] = f(); // creates e[2], copies a into e, then x refers to e[0], y refers to e[1] auto& [xr, yr] = f(); // xr refers to a[0], yr refers to a[1]
std::set<string> myset; if (auto [iter, success] = myset.insert("Hello"); success) do_something_with(iter);
struct S { int x1 : 2; volatile double y1; }; S f(); const auto [x, y] = f(); // x is a const int lvalue identifying the 2-bit bit field // y is a const volatile double lvalue The referenced type defined above is the type returned by | (since C++17) |
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, 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.
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.
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.
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/language/declarations