Declarations
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
attr(optional) declarator ; | | |
---|
attr (since C++11) | - | sequence of any number of attributes |
---|---|---|
declarator | - | A function declarator. |
This declaration must declare a constructor, destructor, or user-defined type conversion function. It can only be used as part of a template declaration, explicit specialization, or explicit instantiation.
- Block declaration (a declaration that can appear inside a block), which, in turn, can be one of the following:
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:
- 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.
the inline specifier is also allowed on variable declarations. | (since C++17) |
---|
- the inline specifier is also allowed on variable declarations.
(since C++17)
- friend specifier, allowed in class and function declarations.
auto decltype specifier | (since C++11) |
---|
- auto
(since C++11)
- previously declared class name (optionally qualified)
template name without template arguments (optionally qualified): see class template deduction | (since C++17) |
---|
- template name without template arguments (optionally qualified): see class template deduction
(since C++17)
- elaborated type specifier
only one type specifier is allowed in a decl-specifier-seq, with the following exceptions: - 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 long (which can appear twice in a row). All other repeats, such as const static const, or virtual inline virtual are errors. | (since C++17) |
---|
Structured binding declaration attr(optional) cv-auto ref-operator(optional) identifier-list = expression ; (1) (since C++17) attr(optional) cv-auto ref-operator(optional) identifier-list { expression } ; (2) (since C++17) attr(optional) cv-auto ref-operator(optional) identifier-list ; (3) (since C++17) attr - sequence of any number of attributes cv-auto - possibly cv-qualified type specifier auto ref-operator - either & or && identifier-list - list of comma-separated identifiers (structured bindings) introduced by this declaration expression - an expression that does not have the comma operator at the top level, and has either array or non-union class type 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: First, a uniquely-named variable e is introduced as follows: If expression has array type A and no ref-operator is present, then e has type cv A, where cv is the cv-qualifiers in the cv-auto sequence, and each element of e is copy- (for (1)) or direct- (for (2,3)) initialized from the corresponding element of expression. Otherwise e is defined as if by using its name instead of identifier-list in the declaration. Let E denote type of the expression e (note that E is never a reference type). If E is an array type whose element type is T, then each identifier in identifier-list becomes the name of an lvalue that refers to the corresponding element of the array. The referenced type for each identifier is T (note that if E is cv-qualified, so is T). The number of identifiers must equal the number of array elements: int a2 = {1,2}; auto f() -> int(&)2 { return a; } auto x,y = f( // creates e2, copies a into e, then x refers to e0, y refers to e1 auto& xr, yr = f( // xr refers to a0, yr refers to a1 Otherwise (if expression has non-union class type), If std::tuple_size | attr(optional) cv-auto ref-operator(optional) identifier-list = expression ; | (1) | (since C++17) | attr(optional) cv-auto ref-operator(optional) identifier-list { expression } ; | (2) | (since C++17) | attr(optional) cv-auto ref-operator(optional) identifier-list ; | (3) | (since C++17) | attr | - | sequence of any number of attributes | cv-auto | - | possibly cv-qualified type specifier auto | ref-operator | - | either & or && | identifier-list | - | list of comma-separated identifiers (structured bindings) introduced by this declaration | expression | - | an expression that does not have the comma operator at the top level, and has either array or non-union class type | (since C++17) |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
attr(optional) cv-auto ref-operator(optional) identifier-list = expression ; | (1) | (since C++17) | |||||||||||||||||||||||
attr(optional) cv-auto ref-operator(optional) identifier-list { expression } ; | (2) | (since C++17) | |||||||||||||||||||||||
attr(optional) cv-auto ref-operator(optional) identifier-list ; | (3) | (since C++17) | |||||||||||||||||||||||
attr | - | sequence of any number of attributes | |||||||||||||||||||||||
cv-auto | - | possibly cv-qualified type specifier auto | |||||||||||||||||||||||
ref-operator | - | either & or && | |||||||||||||||||||||||
identifier-list | - | list of comma-separated identifiers (structured bindings) introduced by this declaration | |||||||||||||||||||||||
expression | - | an expression that does not have the comma operator at the top level, and has either array or non-union class type |
- First, a uniqu
e
ly-name
d variable
e
is introduce
d as follows:
Le
t E
de
note
type
of the
e
xpre
ssion e
(note
that E
is ne
ve
r a re
fe
re
nce
type
).
- If
E
is an array type whose element type isT
, then each identifier in identifier-list becomes the name of an lvalue that refers to the corresponding element of the array.T
hereferenced type
for each identifier isT
(note that ifE
is cv-qualified, so isT
).T
he number of identifiers must equal the number of array elements:
int a2 = {1,2}; auto f() -> int(&)2 { return a; } auto x,y = f( // creates e2, copies a into e, then x refers to e0, y refers to e1 auto& xr, yr = f( // xr refers to a0, yr refers to a1
- Otherwise (if expression has non-union class type),
std::set<string> myset; if (auto iter, success = myset.insert("Hello" success) do_something_with(iter
- Oth
e
rwise
(ifE
i
sa
type
for whichstd::tuple_size
i
s not de
fine
d),e
ve
ry non-sta
tic da
ta
me
mbe
r ofE
must be
a
public dire
ct me
mbe
r ofE
or the
sa
me
una
mbiguous public ba
se
ofE
,a
ndE
ma
y not ha
ve
a
nya
nonymous union me
mbe
r.E
a
chi
de
ntifie
ri
ni
de
ntifie
r-list be
come
sa
n lva
lue
tha
t re
fe
rs to the
ne
xt me
mbe
r ofe
i
n de
cla
ra
tion orde
r (bit fie
ldsa
re
supporte
d the
type
of the
lva
lue
i
s cvT
_i,
whe
re
cvi
s the
cv-qua
lifie
rs ofE
a
ndT
_i i
s the
de
cla
re
d type
of the
i
-th me
mbe
r.T
he
re
ferenced type o
f the
i
-thi
de
ntifie
ri
s cvT
_i.
The
numbe
r ofi
de
ntifie
rs muste
qua
l the
numbe
r of non-sta
tic da
ta
me
mbe
rs.
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 decltype
when applied to an unparenthesized structured binding.
(since C++17)
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, 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) | |
1) The name that is declared.
2) A declarator that uses a qualified identifier (qualified-id) defines or redeclares a previously declared namespace member or class member.
3) Parameter pack, only appears in function parameter lists for variadic function templates.
4) Pointer declarator: the declaration S * D;
declares D
as a pointer to the type determined by decl-specifier-seq S
.
5) Pointer to member declaration: the declaration 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 ::
6) Lvalue reference declarator: the declaration S & D;
declares D
as an lvalue reference to the type determined by decl-specifier-seq S
.
7) Rvalue reference declarator: the declaration S && D;
declares D
as an rvalue reference to the type determined by decl-specifier-seq S
.
8) Array declarator. noptr-declarator any valid declarator, but if it begins with *, &, or &&, it has to be surrounded by parentheses.
9) Function declarator. noptr-declarator any valid declarator, but if it begins with *, &, or &&, it has to be surrounded by parentheses. Note that the outermost function declarator may end with the optional trailing return type.
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
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.