Namespaces
Variants

Identifiers

From cppreference.net
C++ language
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
constexpr (C++11)
consteval (C++20)
constinit (C++20)
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

Un identificador es una secuencia arbitrariamente larga de dígitos, guiones bajos, letras latinas minúsculas y mayúsculas, y la mayoría de los caracteres Unicode.

El primer carácter de un identificador válido debe ser uno de los siguientes:

  • letras latinas mayúsculas A-Z
  • letras latinas minúsculas a-z
  • guion bajo
  • cualquier carácter Unicode con la propiedad XID_Start

Cualquier otro carácter de un identificador válido debe ser uno de los siguientes:

  • dígitos 0-9
  • letras latinas mayúsculas A-Z
  • letras latinas minúsculas a-z
  • guion bajo
  • cualquier carácter Unicode con la propiedad Unicode XID_Continue

Las listas de caracteres con las propiedades XID_Start y XID_Continue se pueden encontrar en DerivedCoreProperties.txt .

Los identificadores distinguen entre mayúsculas y minúsculas (las letras minúsculas y mayúsculas son distintas), y cada carácter es significativo. Cada identificador debe ajustarse a la Normalization Form C .

Nota: El soporte de identificadores Unicode es limitado en la mayoría de implementaciones, ej. gcc (hasta la versión 10) .

Contenidos

En declaraciones

Un identificador puede ser usado para nombrar objetos, referencias, funciones, enumeradores, tipos, miembros de clase, espacios de nombres, plantillas, especializaciones de plantillas, parameter packs (since C++11) , etiquetas goto, y otras entidades, con las siguientes excepciones:

  • Los identificadores que son palabras clave no pueden utilizarse para otros propósitos.
  • El único lugar donde pueden usarse como no-palabras clave es en un attribute-token (por ejemplo, [ [ private ] ] es un atributo válido).
(desde C++11)
  • Los identificadores con significado especial ( final , import , module (desde C++20) y override ) se utilizan explícitamente en un contexto específico en lugar de ser identificadores regulares.
    • A menos que se especifique lo contrario, cualquier ambigüedad sobre si un identificador dado tiene un significado especial se resuelve interpretando el token como un identificador regular.
(desde C++11)
  • Identificadores que aparecen como token o token de preprocesamiento (es decir, no en user-defined-string-literal como operator "" id ) (since C++11) que tengan una de las siguientes formas están reservados:
    • en el espacio de nombres global, identificadores que comienzan con un guion bajo
    • identificadores que contienen un doble guion bajo o comienzan con un guion bajo seguido de una letra mayúscula, excepto los siguientes identificadores:
(desde C++11)
  • las siguientes macros definidas en la biblioteca estándar:
  • las macros de compatibilidad con C __alignas_is_defined y __alignof_is_defined (definidas en <stdalign.h> )
  • la macro de compatibilidad con C __bool_true_false_are_defined (definida en <stdbool.h> )
(desde C++11)
(desde C++20)

"Reservado" aquí significa que los encabezados de la biblioteca estándar #define o declaran dichos identificadores para sus necesidades internas, el compilador puede predefinir identificadores no estándar de ese tipo, y que el algoritmo de name mangling puede asumir que algunos de estos identificadores no están en uso. Si el programador utiliza dichos identificadores, el programa está mal formado, no se requiere diagnóstico.

Además, es comportamiento indefinido #define o #undef ciertos nombres en una unidad de traducción, consulte nombres de macros reservados para más detalles.

Identificadores zombi

A partir de C++14, algunos identificadores han sido eliminados de la biblioteca estándar de C++. Se enumeran en la lista de nombres zombie .

Sin embargo, estos identificadores aún están reservados para estandarización previa en cierto contexto. Los nombres de funciones miembro eliminadas no pueden utilizarse como nombre para macros similares a funciones, y otros nombres de miembros eliminados no pueden utilizarse como nombre para macros similares a objetos en código portable.

En expresiones

Un identificador que nombra una variable, una función, especialización de un concept , (since C++20) o un enumerador puede ser usado como una expresión . El resultado de una expresión que consiste únicamente en el identificador es la entidad nombrada por el identificador. La categoría de valor de la expresión es lvalue si el identificador nombra una función, una variable , un template parameter object (since C++20) , o un miembro de datos, y rvalue (until C++11) prvalue (since C++11) en caso contrario (por ejemplo, un enumerador es an rvalue (until C++11) a prvalue (since C++11) expresión , una especialización de un concept es un bool prvalue (since C++20) ).

Tipo

El tipo de una expresión de identificador es el mismo que el tipo de la entidad que nombra.

Existen las siguientes excepciones:

  • Si la entidad nombrada por el identificador (no calificado) es una entidad local, y resultaría en una expresión lambda intermedia que la captura por copia si se nombrara fuera de un operando no evaluado en la región declarativa donde aparece el identificador, entonces el tipo de la expresión es el tipo de una expresión de acceso a miembro de clase que nombra el miembro de datos no estático que se declararía para dicha captura en el objeto de cierre de la expresión lambda intermedia más interna.
void f()
{
    float x, &r = x;
    [=]
    {
        decltype(x) y1;        // y1 has type float
        decltype((x)) y2 = y1; // y2 has type float const& because this lambda
                               // is not mutable and x is an lvalue
        decltype(r) r1 = y1;   // r1 has type float&
        decltype((r)) r2 = y2; // r2 has type float const&
    };
}
(desde C++20)
(desde C++11)

Identificadores no calificados

Además de identificadores declarados adecuadamente, lo siguiente puede utilizarse en expresiones en el mismo rol:

(desde C++11)
  • un template seguido de su lista de argumentos, como MyTemplate < int > ;
  • el carácter ~ seguido de un nombre de clase, como ~MyClass ;
  • el carácter ~ seguido por un especificador decltype , como ~decltype ( str ) .
(desde C++11)
(desde C++26)

Junto con los identificadores se conocen como expresiones de identificador no calificadas .

Identificadores calificados

Un identificador calificado es un identificador no calificado precedido por un operador de resolución de ámbito :: , y opcionalmente, una secuencia de cualquiera de los siguientes separados por operadores de resolución de ámbito:

  • un nombre de namespace;
  • un nombre de clase;
(desde C++11)
(desde C++26)

Por ejemplo, la expresión std:: string :: npos es una expresión que nombra al miembro estático npos en la clase string en el espacio de nombres std . La expresión :: tolower nombra la función tolower en el espacio de nombres global. La expresión :: std:: cout nombra la variable global cout en el espacio de nombres std , que es un espacio de nombres de nivel superior. La expresión boost :: signals2 :: connection nombra el tipo connection declarado en el espacio de nombres signals2 , que está declarado en el espacio de nombres boost .

La palabra clave template puede aparecer en identificadores calificados cuando sea necesario para desambiguar nombres de plantilla dependientes .

Consulte qualified lookup para obtener los detalles de la búsqueda de nombres para identificadores calificados.

Transformación implícita de acceso a miembros

Si una expresión de identificador E denota un miembro no estático de tipo no-clase de alguna clase C y se satisfacen todas las siguientes condiciones, E se transforma en la expresión de acceso a miembro de clase this - > E :

  • E es potencialmente evaluado .
  • C es la clase envolvente más interna en E .
  • C es una clase base de la clase envolvente más interna en E .

Esta transformación no se aplica en el contexto de definición de plantilla (consulte dependent names ).

struct X
{
    int x;
};
struct B
{
    int b;
};
struct D : B
{
    X d;
    void func()
    {
        d;   // OK, se transformará en this->d
        b;   // OK, se transformará en this->b
        x;   // Error: this->x está mal formado
        d.x; // OK, se transformará en this->d.x
             // en lugar de d.this->x o this->d.this->x
    }
};

Nombres

Un nombre es el uso de uno de los siguientes para referirse a una entidad:

  • un identificador
  • un nombre de operador sobrecargado en notación de función ( operator + , operator new )
  • un nombre de función de conversión definida por el usuario ( operator bool )
  • un nombre de operador de literal definido por el usuario ( operator "" _km )
(desde C++11)
  • un nombre de plantilla seguido de su lista de argumentos ( MyTemplate < int > )

Cada nombre se introduce en el programa mediante una declaración . Un nombre utilizado en más de una unidad de traducción puede referirse a las mismas o diferentes entidades, dependiendo de la vinculación .

Cuando el compilador encuentra un nombre desconocido en un programa, lo asocia con la declaración que introdujo el nombre mediante name lookup , excepto por los dependent names en declaraciones y definiciones de plantillas (para esos nombres, el compilador determina si designan un tipo, una plantilla u otra entidad, lo que puede requerir explicit disambiguation ).

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 1440 C++11 las expresiones decltype precediendo :: podían denotar cualquier tipo solo pueden denotar tipos de clase
o enumeración
CWG 1963 C++11 caracteres definidos por la implementación distintos a dígitos, no-dígitos
y nombres de caracteres universales podían usarse en un identificador
prohibido
CWG 2521 C++11 el identificador en user-defined-string-literal de
un operador literal estaba reservado como es habitual
las reglas son diferentes
CWG 2771 C++98 & a no se transformaba en & this - > a en contextos de clase se transforma
CWG 2777 C++20 el tipo de una expresión de identificador no estaba claro
si nombra un objeto de parámetro de plantilla
aclarado
CWG 2818 C++98 los nombres de macros predefinidos están reservados no están reservados

Véase también

Documentación de C para Identifiers