Identifiers
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.
|
(desde C++11) |
- Los identificadores que son representaciones alternativas para ciertos operadores y signos de puntuación no pueden utilizarse para otros propósitos.
|
(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:
-
-
- macros predefinidos (incluyendo macros de prueba de características del lenguaje ) (desde C++20)
-
| (desde C++11) |
|
(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:
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++11) |
Identificadores no calificados
Además de identificadores declarados adecuadamente, lo siguiente puede utilizarse en expresiones en el mismo rol:
- un operador sobrecargado en notación de función, como operator + o operator new ;
- una función de conversión definida por el usuario , como operator bool ;
|
(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 ;
|
(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 no es el operando derecho de un operador de acceso a miembro .
- Si E es una expresión de identificador calificado, E no es el operando sin paréntesis de un operador de dirección de .
- Se satisface cualquiera de las siguientes condiciones:
-
- E es potencialmente evaluado .
-
Ces la clase envolvente más interna en E . -
Ces 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 )
|
(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
|