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

Ein Identifier ist eine beliebig lange Folge von Ziffern, Unterstrichen, lateinischen Klein- und Großbuchstaben sowie den meisten Unicode-Zeichen.

Das erste Zeichen eines gültigen Identifikators muss eines der folgenden sein:

  • Großbuchstaben des lateinischen Alphabets A-Z
  • Kleinbuchstaben des lateinischen Alphabets a-z
  • Unterstrich
  • jedes Unicode-Zeichen mit der Unicode-Eigenschaft XID_Start

Jedes andere Zeichen eines gültigen Bezeichners muss eines der folgenden sein:

  • Ziffern 0-9
  • lateinische Großbuchstaben A-Z
  • lateinische Kleinbuchstaben a-z
  • Unterstrich
  • jedes Unicode-Zeichen mit der Unicode-Eigenschaft XID_Continue

Die Listen der Zeichen mit den Eigenschaften XID_Start und XID_Continue können in DerivedCoreProperties.txt gefunden werden.

Bezeichner sind case-sensitive (Klein- und Großbuchstaben werden unterschieden), und jedes Zeichen ist signifikant. Jeder Bezeichner muss Normalization Form C entsprechen.

Hinweis: Die Unterstützung von Unicode-Identifikatoren ist in den meisten Implementierungen eingeschränkt, z.B. gcc (bis Version 10) .

Inhaltsverzeichnis

In Deklarationen

Ein Bezeichner kann verwendet werden um zu benennen Objekte, Referenzen, Funktionen, Enumeratoren, Typen, Klassenmitglieder, Namensräume, Templates, Templatespezialisierungen, Parameter Packs (since C++11) , goto-Labels und andere Entitäten, mit folgenden Ausnahmen:

  • Die Bezeichner, die Schlüsselwörter sind, können nicht für andere Zwecke verwendet werden.
  • Der einzige Ort, an dem sie als Nicht-Schlüsselwörter verwendet werden können, ist in einem Attribut-Token (z.B. ist [ [ private ] ] ein gültiges Attribut ).
(seit C++11)
  • Die Bezeichner, die alternative Darstellungen für bestimmte Operatoren und Interpunktionszeichen sind, können nicht für andere Zwecke verwendet werden.
  • Die Bezeichner mit spezieller Bedeutung ( final , import , module (seit C++20) und override ) werden explizit in einem bestimmten Kontext verwendet, anstatt reguläre Bezeichner zu sein.
    • Sofern nicht anders angegeben, wird jede Mehrdeutigkeit bezüglich der speziellen Bedeutung eines Bezeichners dahingehend aufgelöst, dass das Token als regulärer Bezeichner interpretiert wird.
(seit C++11)
  • Bezeichner die als Token oder Präprozessor-Token auftreten (d.h. nicht in user-defined-string-literal wie operator "" id ) (seit C++11) in einer der folgenden Formen sind reserviert:
    • im globalen Namensraum, Bezeichner die mit einem Unterstrich beginnen
    • Bezeichner die einen doppelten Unterstrich enthalten oder mit einem Unterstrich gefolgt von einem Großbuchstaben beginnen, mit Ausnahme der folgenden Bezeichner:
(seit C++11)
  • die folgenden Makros, die in der Standardbibliothek definiert sind:
  • die C-Kompatibilitätsmakros __alignas_is_defined und __alignof_is_defined (definiert in <stdalign.h> )
  • das C-Kompatibilitätsmakro __bool_true_false_are_defined (definiert in <stdbool.h> )
(seit C++11)
(seit C++20)

„Reserviert“ bedeutet hier, dass die Standardbibliotheks-Header #define oder solche Bezeichner für ihre internen Anforderungen deklarieren, der Compiler möglicherweise nicht-normative Bezeichner dieser Art vordefiniert und dass der Name-Mangling-Algorithmus davon ausgehen kann, dass einige dieser Bezeichner nicht in Verwendung sind. Wenn der Programmierer solche Bezeichner verwendet, ist das Programm fehlerhaft, keine Diagnose erforderlich.

Zusätzlich ist es undefiniertes Verhalten, #define oder #undef für bestimmte Namen in einer Übersetzungseinheit zu verwenden. Weitere Details finden Sie unter reservierte Makronamen .

Zombie-Identifikatoren

Ab C++14 wurden einige Bezeichner aus der C++-Standardbibliothek entfernt. Sie sind in der Liste der Zombie-Namen aufgeführt.

Allerdings sind diese Bezeichner in einem bestimmten Kontext weiterhin für frühere Standardisierungen reserviert. Entfernte Member-Funktionsnamen dürfen nicht als Name für funktionsähnliche Makros verwendet werden, und andere entfernte Member-Namen dürfen nicht als Name für objektähnliche Makros in portablem Code verwendet werden.

In Ausdrücken

Ein Bezeichner, der eine Variable, eine Funktion, eine Spezialisierung eines Konzepts , (seit C++20) oder einen Enumerator benennt, kann als Ausdruck verwendet werden. Das Ergebnis eines Ausdrucks, der nur aus dem Bezeichner besteht, ist die durch den Bezeichner benannte Entität. Die Wertkategorie des Ausdrucks ist Lvalue , wenn der Bezeichner eine Funktion, eine Variable , ein Template-Parameter-Objekt (seit C++20) oder ein Datenelement benennt, und Rvalue (bis C++11) Prvalue (seit C++11) andernfalls (z.B. ist ein Enumerator ein Rvalue (bis C++11) ein Prvalue (seit C++11) -Ausdruck , eine Spezialisierung eines Konzepts ist ein boolescher Prvalue (seit C++20) ).

Typ

Der Typ eines Identifikatorausdrucks ist derselbe wie der Typ der Entität, die er benennt.

Folgende Ausnahmen existieren:

  • Wenn die durch den (nicht qualifizierten) Bezeichner benannte Entität eine lokale Entität ist und dazu führen würde, dass ein dazwischenliegender Lambda-Ausdruck sie durch Kopie erfasst, wenn sie außerhalb eines nicht ausgewerteten Operanden im deklarativen Bereich benannt würde, in dem der Bezeichner erscheint, dann ist der Typ des Ausdrucks der Typ eines Klassen-Member-Zugriffsausdrucks , der den nicht-statischen Datenelement benennt, der für eine solche Erfassung im Closure-Objekt des innersten solchen dazwischenliegenden Lambda-Ausdrucks deklariert werden würde.
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&
    };
}
  • Wenn die benannte Entität ein Template-Parameter-Objekt für einen Template-Parameter vom Typ T ist, dann ist der Typ des Ausdrucks const T .
(seit C++20)
(seit C++11)

Unqualifizierte Bezeichner

Neben entsprechend deklarierten Bezeichnern können folgende Elemente in Ausdrücken dieselbe Rolle übernehmen:

(seit C++11)
  • ein Template -Name gefolgt von seiner Argumentenliste, wie MyTemplate < int > ;
  • das Zeichen ~ gefolgt von einem Klassennamen, wie ~MyClass ;
  • das Zeichen ~ gefolgt von einem decltype Spezifizierer, wie ~decltype ( str ) .
(seit C++11)
(seit C++26)

Zusammen mit Bezeichnern werden sie als unqualified identifier expressions bezeichnet.

Qualifizierte Bezeichner

Ein qualifizierter Identifikatorausdruck ist ein unqualifizierter Identifikatorausdruck, dem ein Bereichsauflösungsoperator :: vorangestellt ist, und optional eine Sequenz von beliebigen der folgenden, durch Bereichsauflösungsoperatoren getrennten Elementen:

  • ein Namespace-Name;
  • ein Klassenname;
(seit C++11)
(seit C++26)

Beispielsweise ist der Ausdruck std:: string :: npos ein Ausdruck, der das statische Mitglied npos in der Klasse string im Namensraum std benennt. Der Ausdruck :: tolower benennt die Funktion tolower im globalen Namensraum. Der Ausdruck :: std:: cout benennt die globale Variable cout im Namensraum std , welcher ein oberster Namensraum ist. Der Ausdruck boost :: signals2 :: connection benennt den Typ connection , der im Namensraum signals2 deklariert ist, welcher wiederum im Namensraum boost deklariert ist.

Das Schlüsselwort template kann in qualifizierten Identifikatoren erscheinen, wenn es notwendig ist, um abhängige Template-Namen zu disambiguieren.

Siehe qualified lookup für die Details der Namenssuche für qualifizierte Identifikatoren.

Implizite Member-Zugriffstransformation

Wenn ein Bezeichnerausdruck E ein nicht-statisches Datenelement einer Klasse C bezeichnet und alle folgenden Bedingungen erfüllt sind, wird E in den Klassenmember-Zugriffsausdruck this - > E transformiert:

  • E ist nicht der rechte Operand eines Member-Zugriffsoperators .
  • Wenn E ein qualifizierter Identifikatorausdruck ist, E nicht der ungeklammerte Operand eines Adressoperators ist.
  • Eine der folgenden Bedingungen ist erfüllt:
  • E wird potenziell ausgewertet .
  • C ist die innerste umschließende Klasse an E .
  • C ist eine Basisklasse der innersten umschließenden Klasse an E .

Diese Transformation findet im Template-Definitionskontext keine Anwendung (siehe dependent names ).

struct X
{
    int x;
};
struct B
{
    int b;
};
struct D : B
{
    X d;
    void func()
    {
        d;   // OK, wird in this->d transformiert
        b;   // OK, wird in this->b transformiert
        x;   // Fehler: this->x ist ungültig
        d.x; // OK, wird in this->d.x transformiert
             // anstelle von d.this->x oder this->d.this->x
    }
};

Namen

Ein name ist die Verwendung einer der folgenden Möglichkeiten, um sich auf eine Entität zu beziehen:

  • ein Bezeichner
  • ein überladener Operatorname in Funktionsschreibweise ( operator + , operator new )
  • ein Name einer benutzerdefinierten Konvertierungsfunktion ( operator bool )
  • ein benutzerdefinierter Literal-Operator-Name ( operator "" _km )
(seit C++11)
  • ein Template-Name gefolgt von seiner Argumentenliste ( MyTemplate < int > )

Jeder Name wird in das Programm durch eine Deklaration eingeführt. Ein Name, der in mehr als einer Übersetzungseinheit verwendet wird, kann sich auf dieselbe oder verschiedene Entitäten beziehen, abhängig von der Linkage .

Wenn der Compiler auf einen unbekannten Namen in einem Programm stößt, verknüpft er ihn mit der Deklaration, die den Namen mittels Namenssuche eingeführt hat, mit Ausnahme der dependent names in Template-Deklarationen und -Definitionen (für diese Namen bestimmt der Compiler, ob sie einen Typ, ein Template oder eine andere Entität bezeichnen, was explizite Disambiguierung erfordern kann).

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 1440 C++11 decltype-Ausdrücke vor :: konnten jeden Typ bezeichnen können nur Klassen-
oder Aufzählungstypen bezeichnen
CWG 1963 C++11 implementierungsdefinierte Zeichen außer Ziffern, Nicht-Ziffern
und universellen Zeichennamen konnten in einem Bezeichner verwendet werden
verboten
CWG 2521 C++11 der Bezeichner in user-defined-string-literal eines
Literaloperators war wie üblich reserviert
die Regeln sind unterschiedlich
CWG 2771 C++98 & a wurde nicht in & this - > a in Klassenkontexten transformiert wird transformiert
CWG 2777 C++20 der Typ eines Identifikatorausdrucks war unklar,
wenn er ein Template-Parameterobjekt benennt
klargestellt
CWG 2818 C++98 vordefinierte Makronamen sind reserviert sie sind nicht reserviert

Siehe auch

C-Dokumentation für Identifiers