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 lvalueThe 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