An identifier is an arbitrarily long sequence of digits, underscores, lowercase and uppercase Latin letters, and most Unicode characters.
Syntax
The first character of a valid identifier must be one of the following:
uppercase Latin letters A-Z
lowercase Latin letters a-z
underscore
any Unicode character with the Unicode property
Any other character of a valid identifier must be one of the following:
digits 0-9
uppercase Latin letters A-Z
lowercase Latin letters a-z
underscore
any Unicode character with the Unicode property
The lists of characters with properties XID_Start and XID_Continue can be found in
.
Identifiers are case-sensitive (lowercase and uppercase letters are distinct), and every character is significant. Every identifier must conform to
.
Note: Support of Unicode identifiers is limited in most implementations, e.g.
.
In declarations
An identifier can be used
objects, references, functions, enumerators, types, class members, namespaces, templates, template specializations, parameter packs(since C++11), goto labels, and other entities, with the following exceptions:
The identifiers that are
cannot be used for other purposes.
The only place they can be used as non-keywords is in an attribute-token (e.g. [[private]] is a valid
).
(since C++11)The identifiers that are
for certain operators and punctuators cannot be used for other purposes.
The identifiers with special meaning (final, import, module(since C++20) and override) are used explicitly in a certain context rather than being regular identifiers. Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier.
(since C++11)Identifiers that appear as a token or preprocessing token (i.e., not in user-defined-string-literal like operator""id)(since C++11) of one of the following forms are reserved: in the global namespace, identifiers that begin with an underscore
identifiers that contain a double underscore or begin with an underscore followed by an uppercase letter, except the following identifiers:
(including
)(since C++20)
the following macros defined in the standard library:
the
_PRINTF_NAN_LEN_MAX, (since C++26)_IOFBF, _IOLBF and _IONBF
“Reserved” here means that the standard library headers #define or declare such identifiers for their internal needs, the compiler may predefine non-standard identifiers of that kind, and that name mangling algorithm may assume that some of these identifiers are not in use. If the programmer uses such identifiers, the program is ill-formed, no diagnostic required.
In addition, it is undefined behavior to #define or #undef certain names in a translation unit, see
for more details.
Zombie identifiers
As of C++14, some identifiers are removed from the C++ standard library. They are listed in the
.
However, these identifiers are still reserved for previous standardization in a certain context. Removed member function names may not be used as a name for function-like macros, and other removed member names may not be used as a name for object-like macros in portable code.
In expressions
An identifier that names a variable, a function, specialization of a
,(since C++20) or an enumerator can be used as an
. The result of an expression consisting of just the identifier is the entity named by the identifier. The
of the expression is lvalue if the identifier names a function, a variable, a
(since C++20), or a data member, and rvalue(until C++11)prvalue(since C++11) otherwise (e.g. an
is an rvalue(until C++11)a prvalue(since C++11) expression, a specialization of a concept is a bool prvalue(since C++20)).
Type
The type of an identifier expression is the same as the type of the entity it names.
The following exceptions exist:
If the entity named by the (unqualified) identifier is a local entity, and would result in an intervening
capturing it by copy if it were named outside of an unevaluated operand in the declarative region in which the identifier appears, then the type of the expression is the type of a
class member access expression
naming the non-static data member that would be declared for such a capture in the closure object of the innermost such intervening lambda expression.
voidf(){floatx,&r=x;[=]{decltype(x)y1;// y1 has type floatdecltype((x))y2=y1;// y2 has type float const& because this lambda// is not mutable and x is an lvaluedecltype(r)r1=y1;// r1 has type float&decltype((r))r2=y2;// r2 has type float const&};}If the entity named is a
for a template parameter of type T, the type of the expression is constT.
(since C++20)(since C++11)Unqualified identifiers
Besides suitably declared identifiers, the following can be used in expressions in the same role:
an
name in function notation, such as operator+ or operatornew;
a
user-defined conversion function
name, such as operatorbool;
a
name followed by its argument list, such as MyTemplate<int>;
the character ~ followed by a class name, such as ~MyClass;
the character ~ followed by a
specifier, such as ~decltype(str).
(since C++11)Together with identifiers they are known as unqualified identifier expressions.
Qualified identifiers
A qualified identifier expression is an unqualified identifier expression prepended by a scope resolution operator ::, and optionally, a sequence of any of the following separated by scope resolution operators:
a namespace name;
a class name;
an enumeration name;
a
denoting a class or enumeration type.
(since C++11)a
denoting a class or enumeration type.
a
designating a class or enumeration type, or a namespace.
a
designating a class template or alias template, followed by a template argument list, collectively denoting a class or enumeration type.
(since C++26)For example, the expression std::string::npos is an expression that names the static member npos in the class string in namespace std. The expression ::tolower names the function tolower in the global namespace. The expression ::std::cout names the global variable cout in namespace std, which is a top-level namespace. The expression boost::signals2::connection names the type connection declared in namespace signals2, which is declared in namespace boost.
The keyword
may appear in qualified identifiers as necessary to disambiguate
.
See
for the details of the name lookup for qualified identifiers.
Implicit member access transformation
If an identifier expression E denotes a non-static non-type member of some class C and all following conditions are satisfied, E is transformed into the class member access expression this->E:
E is not the right operand of a
.
If E is a qualified identifier expression, E is not the un-parenthesized operand of an
.
Any of the following conditions is satisfied:
E is
.
C is the innermost enclosing class at E.
C is a base class of the innermost enclosing class at E.
This transformation does not apply in the template definition context (see
).
structX{intx;};structB{intb;};structD:B{Xd;voidfunc(){d;// OK, will be transformed into this->db;// OK, will be transformed into this->bx;// Error: this->x is ill-formedd.x;// OK, will be transformed into this->d.x// instead of d.this->x or this->d.this->x}};Names
A name is the use of one of the following to refer to an entity:
an identifier
an overloaded operator name in function notation (operator+, operatornew)
a user-defined conversion function name (operatorbool)
a user-defined literal operator name (operator""_km)
(since C++11)a template name followed by its argument list (MyTemplate<int>)
Every name is introduced into the program by a
. A name used in more than one translation unit may refer to the same or different entities, depending on
.
When the compiler encounters an unknown name in a program, it associates it with the declaration that introduced the name by means of
, except for the
in template declarations and definitions (for those names, the compiler determines whether they name a type, a template, or some other entity, which may require
).
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior
C++11 decltype expressions preceding :: could denote any type can only denote class
or enumeration types
C++11 implementation-defined characters other than digits, non-digits
and universal character names could be used in an identifier prohibited
C++11 the identifier in user-defined-string-literal of
a literal operator was reserved as usual the rules are different
C++98 &a was not transformed into &this->a in class contexts it is transformed
C++20 the type of an identifier expression was unclear
if it names a template parameter object made clear
C++98 predefined macro names are reserved they are not reserved See also