General topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
Eachdeclaration that appears in a C++ program is only visible in some possibly discontiguousscopes .
Within a scope,unqualified name lookup can be used to associate a name with its declaration.
Contents |
Each program has aglobal scope , whichcontains the entire program.
Every other scopeS
is introduced by one of the following:
(since C++26) |
S
always appear in another scope, which therebycontainsS
.
Anenclosing scope at a program point is any scope that contains it; the smallest such scope is said to be theimmediate scope at that point.
A scopeintervenes between a program pointP
and a scopeS
(that does not containP
) if it is or containsS
but does not containP
.
Theparent scope of any scopeS
that is not atemplate parameter scope is the smallest scope that containsS
and is not a template parameter scope.
Unless otherwise specified:
An entitybelongs to a scopeS
ifS
is the target scope of a declaration of the entity.
// global scope scope// scope S Tint x;// ─┐ // program point X// │{// │ ─┐{// │ │ ─┐int y;// │ │ │ // program point Y}// │ │ ─┘}// ─┘ ─┘
In the program above:
S
and scopeT
contains program pointY
.Y
.S
andT
, and scopeS
contains scopeT
.T
is the smallest scope among all three, which means:T
is the immediate scope at program pointY
.T
at its locus.T
is the target scope of the declaration ofy.T
.S
is the parent scope of scopeT
, and the global scope is the parent scope of scopeS
.S
intervenes between program pointX
and scopeT
.Each
introduces ablock scope that includes the statement or handler.
A variable that belongs to a block scope is ablock variable (also known as local variable).
int i=42;int a[10]; for(int i=0; i<10; i++)// inner “i” inhabits the block scope a[i]= i;// introduced by the for-statement int j= i;// j = 42
If the declaration inhabits a block scopeS
and declares a function or uses theextern specifier, the declaration shall not be attached to anamed module (since C++20), its target scope is a larger enclosing scope (the innermost enclosing namespace scope), but the name is bound in their immediate scopeS
.
If a declaration that is not aname-independent declaration and(since C++26) that binds a name in the block scopeS
of
| (since C++11) |
potentially conflicts with a declaration whose target scope is the parent scope ofS
, the program is ill-formed.
if(int x= f())// declares “x”{// the if-block is a substatement of the if-statementint x;// error: redeclaration of “x”}else{// the else-block is also a substatement of the if-statementint x;// error: redeclaration of “x”} void g(int i){externint i;// error: redeclaration of “i”}
Eachparameter declarationP
introduces afunction parameter scope that includesP
.
| (since C++11) |
| (since C++17) |
| (since C++20) |
int f(int n)// the declaration of the parameter “n”{// introduces a function parameter scope/* ... */}// the function parameter scope ends here
Lambda scopeEachlambda expression introduces alambda scope that starts immediately after Thecaptures with initializers of a lambda expressionE inhabit the lambda scope introduced byE. auto lambda=[x=1, y]()// this lambda expression introduces a lambda scope,{// it is the target scope of capture “x”/* ... */};// the lambda scope ends before the semicolon | (since C++14) |
Everynamespace definition for a namespaceN
introduces anamespace scopeS
that includes thedeclarations for every namespace definition forN
.
For each non-friend redeclaration or specialization whose target scope isS
or is contained byS
, the following portions are also included in scopeS
:
Theglobal scope is the namespace scope of theglobal namespace.
namespace V// the namespace definition of “V”{// introduces a namespace scope “S”// the first part of scope “S” begins herevoid f();// the first part of scope “S” ends here} void V::f()// the portion after “f” is also a part of scope “S”{void h();// declares V::h}// the second part of scope “S” ends here
Each declaration of a class or class templateC
introduces aclass scopeS
that includes themember-specification of theclass definition ofC
.
For each non-friend redeclaration or specialization whose target scope isS
or is contained byS
, the following portions are also included in scopeS
:
class C// the class definition of “C”{// introduces a class scope “S”// the first part of scope “S” begins herevoid f();// the first part of scope “S” ends here} void C::f()// the portion after “f” is also a part of scope “S”{/* ... */}// the second part of scope “S” ends here
Each declaration of an enumerationE
introduces anenumeration scope that includes theenumerator-list of the non-opaque(since C++11)enumeration declaration ofE
(if present).
enumclass E// the enumeration declaration of “E”{// introduces an enumeration scope “S”// scope “S” begins here e1, e2, e3// scope “S” ends here}
Eachtemplate template parameter introduces atemplate parameter scope that includes the entire template parameter list and therequire clauses(since C++20) of that template template parameter.
Each template declarationD
introduces atemplate parameter scopeS
that extends from the beginning of the template parameter list ofD
to the end ofD
. Any declaration outside the template parameter list that would inhabitS
instead inhabits the same scope asD
.
Only template parameters belong to a template parameter scope, and only template parameter scopes have a template parameter scope as a parent scope.
// the class template declaration of “X”// introduces a template parameter scope “S1”template<// scope “S1” begins heretemplate// the template template parameter “T”// introduces another template parameter scope “S2”<typename T1typename T2> requires std::convertible_from<T1, T2>// scope “S2” ends hereclass T,typename U>class X;// scope “S1” ends before the semicolon namespace N{template<typename T>using A=struct X;// “X” inhabits the same scope as template// declaration, namely the scope of “N”}
Contract-assertion scopeEachcontract assertion If apostcondition assertion has anidentifier which is notname-independent, and the postcondition assertion is associated with a functionfuncpotentially conflicts with a declaration
| (since C++26) |
In general, a name is visible after thelocus of its first declaration, which is located as follows.
The locus of a name declared in a simple declaration is immediately after that name'sdeclarator and before its initializer, if any.
int x=32;// outer x is in scope {int x= x;// inner x is in scope before the initializer (= x)// this does not initialize inner x with the value of outer x (32),// this initializes inner x with its own (indeterminate) value} std::function<int(int)> f=[&](int n){return n>1? n* f(n-1): n;};// the name of the function f is in scope in the lambda and can// be correctly captured by reference, giving a recursive function
constint x=2;// outer x is in scope {int x[x]={};// inner x is in scope before the initializer (= {}),// but after the declarator (x[x])// in the declarator, outer x is still in scope// this declares an array of 2 int}
The locus of a class or class template declaration is immediately after the identifier that names the class (or thetemplate-id that names the template specialization) in itsclass-head. The class or class template name is already in scope in the list of base classes.
struct S:std::enable_shared_from_this<S>{};// S is in scope at the colon
The locus ofenum specifier or opaque enum declaration(since C++11) is immediately after the identifier that names the enumeration.
enum E:int// E is in scope at the colon{ A= sizeof(E)};
The locus of atype alias or alias template declaration is immediately after the type-id to which the alias refers.
using T=int;// outer T is in scope at the semicolon {using T= T*;// inner T is in scope at the semicolon,// outer T is still in scope before the semicolon// same as T = int*}
The locus for a declarator in ausing declaration that does not name a constructor is immediately after the declarator.
template<int N>class Base{protected:staticconstint next= N+1;staticconstint value= N;}; struct Derived: Base<0>, Base<1>, Base<2>{using Base<0>::next,// next is in scope at the comma Base<next>::value;// Derived::value is 1};
The locus of an enumerator is immediately after its definition (not before the initializer as it is for variables).
constint x=12; {enum{ x= x+1,// enumerator x is in scope at the comma,// outer x is in scope before the comma,// enumerator x is initialized to 13 y= x+1// y is initialized to 14};}
The locus for aninjected-class-name is immediately following the opening brace of its class (or class template) definition.
template<typename T>struct Array// : std::enable_shared_from_this<Array> // error: the injected class name is not in scope:std::enable_shared_from_this< Array<T>>// OK: the template-name Array is in scope{// the injected class name Array is now in scope as if a public member name Array* p;// pointer to Array<T>};
The locus of the implicit declaration for a function-local predefined variable__func__ is immediately before the function body of a function definition. | (since C++11) |
The locus of astructured binding declaration is immediately after theidentifier-list, but structured binding initializers are prohibited from referring to any of the names being declared. | (since C++17) |
The locus of the variable or the structured bindings(since C++17) declared in therange-declaration of arange-for loop is immediately after therange-expression. std::vector<int> x; for(auto x: x)// vector x is in scope before the closing parenthesis,// auto x is in scope at the closing parenthesis{// the auto x is in scope} | (since C++11) |
The locus of atemplate parameter is immediately after its complete template parameter (including the optional default argument).
typedefunsignedchar T; template<class T= T,// template parameter T is in scope at the comma,// typedef name of unsigned char is in scope before the comma T// template parameter T is in scope N=0>struct A{};
The locus of apostcondition assertion with anidentifier is immediately after its | (since C++26) |
The locus of aconcept definition is immediately after the concept name, but concept definitions are prohibited from referring to the concept name being declared. | (since C++20) |
The locus of a namednamespace definition is immediately after the namespace name.
This section is incomplete Reason: remainder of [basic.scope.pdecl] |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 2793 | C++98 | anextern declaration in a block scope could conflict with another declaration in the parent scope | prohibited |
C documentation forScope |