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 identifiant est une séquence arbitrairement longue de chiffres, de traits de soulignement, de lettres latines minuscules et majuscules, et de la plupart des caractères Unicode.

Le premier caractère d'un identifiant valide doit être l'un des suivants :

  • lettres latines majuscules A-Z
  • lettres latines minuscules a-z
  • trait de soulignement
  • tout caractère Unicode possédant la propriété Unicode XID_Start

Tout autre caractère d'un identifiant valide doit être l'un des suivants :

  • chiffres 0-9
  • lettres latines majuscules A-Z
  • lettres latines minuscules a-z
  • tiret bas
  • tout caractère Unicode possédant la propriété Unicode XID_Continue

Les listes de caractères avec les propriétés XID_Start et XID_Continue peuvent être trouvées dans DerivedCoreProperties.txt .

Les identifiants sont sensibles à la casse (les minuscules et majuscules sont distinctes), et chaque caractère est significatif. Chaque identifiant doit être conforme à la Normalization Form C .

Remarque : La prise en charge des identifiants Unicode est limitée dans la plupart des implémentations, par exemple gcc (jusqu'à la version 10) .

Table des matières

Dans les déclarations

Un identifiant peut être utilisé pour nommer des objets, des références, des fonctions, des énumérateurs, des types, des membres de classe, des espaces de noms, des templates, des spécialisations de templates, des packs de paramètres (depuis C++11) , des étiquettes goto, et d'autres entités, avec les exceptions suivantes :

  • Les identifiants qui sont des mots-clés ne peuvent pas être utilisés à d'autres fins.
  • Le seul endroit où ils peuvent être utilisés comme non-mots-clés est dans un attribute-token (par exemple [ [ private ] ] est un attribut valide).
(depuis C++11)
  • Les identifiants ayant une signification spéciale ( final , import , module (depuis C++20) et override ) sont utilisés explicitement dans un contexte spécifique plutôt que d'être des identifiants ordinaires.
    • Sauf indication contraire, toute ambiguïté quant à savoir si un identifiant donné a une signification spéciale est résolue en interprétant le jeton comme un identifiant ordinaire.
(depuis C++11)
  • Identifiants qui apparaissent comme un jeton ou un jeton de prétraitement (c'est-à-dire pas dans user-defined-string-literal comme operator "" id ) (depuis C++11) ayant l'une des formes suivantes sont réservés :
    • dans l'espace de noms global, les identifiants qui commencent par un trait de soulignement
    • les identifiants qui contiennent un double trait de soulignement ou commencent par un trait de soulignement suivi d'une lettre majuscule, à l'exception des identifiants suivants :
(depuis C++11)
  • les macros suivantes définies dans la bibliothèque standard :
  • les macros de compatibilité C __alignas_is_defined et __alignof_is_defined (définies dans <stdalign.h> )
  • la macro de compatibilité C __bool_true_false_are_defined (définie dans <stdbool.h> )
(depuis C++11)
(depuis C++20)

« Réservé » signifie ici que les en-têtes standards de la bibliothèque #define ou déclarent ces identifiants pour leurs besoins internes, le compilateur peut prédéfinir des identifiants non standards de ce type, et l'algorithme de mangling de noms peut supposer que certains de ces identifiants ne sont pas utilisés. Si le programmeur utilise de tels identifiants, le programme est mal formé, aucun diagnostic requis.

De plus, il est un comportement indéfini de #define ou #undef certains noms dans une unité de traduction, consultez les noms de macros réservés pour plus de détails.

Identifiants zombies

À partir de C++14, certains identifiants sont supprimés de la bibliothèque standard C++. Ils sont listés dans la liste des noms zombies .

Cependant, ces identifiants restent réservés pour la normalisation précédente dans un certain contexte. Les noms de fonctions membres supprimées ne peuvent pas être utilisés comme nom pour des macros de type fonction, et les autres noms de membres supprimés ne peuvent pas être utilisés comme nom pour des macros de type objet dans du code portable.

Dans les expressions

Un identifiant qui nomme une variable, une fonction, une spécialisation d'un concept , (depuis C++20) ou un énumérateur peut être utilisé comme expression . Le résultat d'une expression constituée uniquement de l'identifiant est l'entité nommée par l'identifiant. La catégorie de valeur de l'expression est lvalue si l'identifiant nomme une fonction, une variable , un objet paramètre de modèle (depuis C++20) , ou un membre de données, et rvalue (jusqu'à C++11) prvalue (depuis C++11) sinon (par exemple, un énumérateur est une expression rvalue (jusqu'à C++11) une expression prvalue (depuis C++11) , une spécialisation d'un concept est une prvalue booléenne (depuis C++20) ).

Type

Le type d'une expression d'identifiant est le même que le type de l'entité qu'il nomme.

Les exceptions suivantes existent :

  • Si l'entité nommée par l'identifiant (non qualifié) est une entité locale, et entraînerait une expression lambda intermédiaire la capturant par copie si elle était nommée en dehors d'un opérande non évalué dans la région déclarative où l'identifiant apparaît, alors le type de l'expression est le type d'une expression d'accès membre de classe nommant le membre de données non statique qui serait déclaré pour une telle capture dans l'objet de fermeture de l'expression lambda intermédiaire la plus imbriquée.
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&
    };
}
(depuis C++20)
(depuis C++11)

Identifiants non qualifiés

En plus des identifiants dûment déclarés, les éléments suivants peuvent être utilisés dans les expressions dans le même rôle :

(depuis C++11)
  • un nom de template suivi de sa liste d'arguments, tel que MyTemplate < int > ;
  • le caractère ~ suivi d'un nom de classe, tel que ~MyClass ;
  • le caractère ~ suivi d'un spécificateur decltype , tel que ~decltype ( str ) .
(depuis C++11)
(depuis C++26)

Ensemble avec les identifiants, ils sont connus sous le nom d' expressions d'identifiants non qualifiés .

Identifiants qualifiés

Un expression d'identifiant qualifié est un expression d'identifiant non qualifié précédé d'un opérateur de résolution de portée :: , et optionnellement, une séquence de l'un des éléments suivants séparés par des opérateurs de résolution de portée :

  • un nom de namespace ;
  • un nom de classe ;
(depuis C++11)
(depuis C++26)

Par exemple, l'expression std:: string :: npos est une expression qui désigne le membre statique npos dans la classe string de l'espace de noms std . L'expression :: tolower désigne la fonction tolower dans l'espace de noms global. L'expression :: std:: cout désigne la variable globale cout dans l'espace de noms std , qui est un espace de noms de premier niveau. L'expression boost :: signals2 :: connection désigne le type connection déclaré dans l'espace de noms signals2 , qui est déclaré dans l'espace de noms boost .

Le mot-clé template peut apparaître dans les identifiants qualifiés si nécessaire pour lever l'ambiguïté des noms de template dépendants .

Voir qualified lookup pour les détails de la recherche de nom pour les identifiants qualifiés.

Transformation d'accès implicite aux membres

Si une expression d'identificateur E désigne un membre non-type non-statique d'une classe C et que toutes les conditions suivantes sont satisfaites, E est transformée en expression d'accès au membre de classe this - > E :

  • E est potentiellement évalué .
  • C est la classe englobante la plus interne à E .
  • C est une classe de base de la classe englobante la plus interne à E .

Cette transformation ne s'applique pas dans le contexte de définition de template (voir dependent names ).

struct X
{
    int x;
};
struct B
{
    int b;
};
struct D : B
{
    X d;
    void func()
    {
        d;   // OK, sera transformé en this->d
        b;   // OK, sera transformé en this->b
        x;   // Erreur : this->x est incorrect
        d.x; // OK, sera transformé en this->d.x
             // au lieu de d.this->x ou this->d.this->x
    }
};

Noms

Un nom est l'utilisation de l'un des éléments suivants pour faire référence à une entité :

  • un identifiant
  • un nom d'opérateur surchargé en notation fonction ( operator + , operator new )
  • un nom de fonction de conversion définie par l'utilisateur ( operator bool )
  • un nom d'opérateur de littéral défini par l'utilisateur ( operator "" _km )
(depuis C++11)
  • un nom de template suivi de sa liste d'arguments ( MyTemplate < int > )

Chaque nom est introduit dans le programme par une déclaration . Un nom utilisé dans plus d'une unité de traduction peut faire référence aux mêmes entités ou à des entités différentes, selon la liaison .

Lorsque le compilateur rencontre un nom inconnu dans un programme, il l'associe à la déclaration qui a introduit le nom au moyen d'une recherche de nom , à l'exception des noms dépendants dans les déclarations et définitions de templates (pour ces noms, le compilateur détermine s'ils désignent un type, un template ou une autre entité, ce qui peut nécessiter une désambiguïsation explicite ).

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement corrigé
CWG 1440 C++11 les expressions decltype précédant :: pouvaient désigner n'importe quel type ne peuvent désigner que des types classe
ou énumération
CWG 1963 C++11 les caractères définis par l'implémentation autres que les chiffres, non-chiffres
et les noms de caractères universels pouvaient être utilisés dans un identifiant
interdit
CWG 2521 C++11 l'identifiant dans user-defined-string-literal d'un
opérateur littéral était réservé comme d'habitude
les règles sont différentes
CWG 2771 C++98 & a n'était pas transformé en & this - > a dans les contextes de classe il est transformé
CWG 2777 C++20 le type d'une expression identifiant n'était pas clair
si elle nomme un objet paramètre de template
clarifié
CWG 2818 C++98 les noms de macros prédéfinies sont réservés ils ne sont pas réservés

Voir aussi

Documentation C pour Identifiers