Bezeichner
Ein Bezeichner ist eine beliebig lange Folge von Ziffern, Unterstrichen, Klein- und Großbuchstaben sowie den meisten Unicode-Zeichen.
Das erste Zeichen eines gültigen Bezeichners muss eines der folgenden sein
- Großbuchstaben A-Z
- Kleinbuchstaben 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
- Großbuchstaben A-Z
- 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 finden Sie in DerivedCoreProperties.txt.
Bezeichner sind Groß-/Kleinschreibung-sensitiv (Klein- und Großbuchstaben sind unterschiedlich) und jedes Zeichen ist bedeutsam. Jeder Bezeichner muss der Normalisierungsform C entsprechen.
Hinweis: Die Unterstützung von Unicode-Bezeichnern ist in den meisten Implementierungen begrenzt, z. B. gcc (bis Version 10).
Inhalt |
[bearbeiten] In Deklarationen
Ein Bezeichner kann verwendet werden, um Objekte, Referenzen, Funktionen, Aufzählungselemente, Typen, Klassenmember, Namespaces, Templates, Template-Spezialisierungen, Parameter-Packs(seit C++11), goto-Labels und andere Entitäten zu benennen, mit den folgenden Ausnahmen
- Die Bezeichner, die Schlüsselwörter sind, dürfen nicht für andere Zwecke verwendet werden.
|
(seit C++11) |
- Die Bezeichner, die alternative Darstellungen für bestimmte Operatoren und Satzzeichen sind, dürfen nicht für andere Zwecke verwendet werden.
|
(seit C++11) |
- Bezeichner , die als Token oder Präprozessor-Token erscheinen (d. h. nicht in benutzerdefinierten Zeichenkettenliteralen wie operator ""id)(seit C++11) der folgenden Formen sind reserviert
- im globalen Namespace, Bezeichner, die mit einem Unterstrich beginnen
- Bezeichner, die einen doppelten Unterstrich enthalten oder mit einem Unterstrich gefolgt von einem Großbuchstaben beginnen, außer den folgenden Bezeichnern
- Vordefinierte Makros (einschließlich Sprach-Feature-Testmakros)(seit C++20)
| (seit C++11) |
|
(seit C++11) |
| (seit C++20) |
„Reserviert“ bedeutet hier, dass die Standardbibliotheks-Header solche Bezeichner für ihre internen Zwecke #definen oder deklarieren, der Compiler kann nicht standardmäßige Bezeichner dieser Art vordefinieren und der Name-Mangling-Algorithmus kann davon ausgehen, dass einige dieser Bezeichner nicht verwendet werden. Wenn der Programmierer solche Bezeichner verwendet, ist das Programm ill-formed, keine Diagnose erforderlich.
Darüber hinaus ist es undefiniertes Verhalten, bestimmte Namen in einer Translation Unit #definen oder #undefn. Siehe reservierte Makronamen für weitere Details.
[bearbeiten] Zombie-Bezeichner
Ab C++14 werden einige Bezeichner aus der C++-Standardbibliothek entfernt. Sie sind in der Liste der Zombie-Namen aufgeführt.
Diese Bezeichner sind jedoch weiterhin für die vorherige Standardisierung in einem bestimmten Kontext reserviert. Entfernte Member-Funktionsnamen dürfen nicht als Namen für funktionsähnliche Makros verwendet werden, und andere entfernte Member-Namen dürfen in portablem Code nicht als Namen für objektähnliche Makros verwendet werden.
[bearbeiten] In Ausdrücken
Ein Bezeichner, der eine Variable, eine Funktion, eine Spezialisierung eines Konzepts,(seit C++20) oder ein Aufzählungselement 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, einen Nicht-Typ-Template-Parameter(seit C++20) oder ein Datenmember benennt, und andernfalls rvaluervalue(bis C++11)prvalue(seit C++11) (z. B. ist ein Aufzählungselement ein rvalue(bis C++11)prvalue(seit C++11) Ausdruck, eine Spezialisierung eines Konzepts ist ein boolescher prvalue(seit C++20)).
[bearbeiten] Typ
Der Typ eines Bezeichnerausdrucks ist derselbe wie der Typ der Entität, die er benennt.
|
Es gibt die folgenden Ausnahmen
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& }; }
|
(seit C++11) |
[bearbeiten] Unqualifizierte Bezeichner
Neben ordnungsgemäß deklarierten Bezeichnern können die folgenden in Ausdrücken in derselben Rolle verwendet werden
- ein Name für einen überladenen Operator in Funktionsnotation, wie z. B. operator+ oder operator new;
- ein Name für eine benutzerdefinierte Konvertierungsfunktion, wie z. B. operator bool;
|
(seit C++11) |
- ein Template-Name gefolgt von seiner Argumentliste, wie z. B. MyTemplate<int>;
- das Zeichen ~ gefolgt von einem Klassennamen, wie z. B. ~MyClass;
|
(seit C++11) |
|
(seit C++26) |
Zusammen mit Bezeichnern werden sie als unqualifizierte Bezeichner-Ausdrücke bezeichnet.
[bearbeiten] Qualifizierte Bezeichner
Ein qualifizierter Bezeichner-Ausdruck ist ein unqualifizierter Bezeichner-Ausdruck, dem ein Scope-Resolution-Operator :: vorangestellt ist, und optional eine Sequenz der folgenden, durch Scope-Resolution-Operatoren getrennt:
- ein Namespace-Name;
- ein Klassenname;
|
(seit C++11) |
|
(seit C++26) |
Beispielsweise ist der Ausdruck std::string::npos ein Ausdruck, der den statischen Member npos in der Klasse string im Namespace std benennt. Der Ausdruck ::tolower benennt die Funktion tolower im globalen Namespace. Der Ausdruck ::std::cout benennt die globale Variable cout im Namespace std, welcher ein Top-Level-Namespace ist. Der Ausdruck boost::signals2::connection benennt den Typ connection, der im Namespace signals2 deklariert ist, welcher im Namespace boost deklariert ist.
Das Schlüsselwort template kann in qualifizierten Bezeichnern erscheinen, um abhängige Template-Namen zu disambiguieren.
Siehe qualifizierte Suche für Details zur Namenssuche für qualifizierte Bezeichner.
[bearbeiten] Implizite Member-Zugriffs-Transformation
Wenn ein Bezeichner-Ausdruck E einen nicht-statischen Nicht-Typ-Member einer Klasse C bezeichnet und alle folgenden Bedingungen erfüllt sind, wird E in den Klassenmember-Zugriffs-Ausdruck this->E umgewandelt
- E ist nicht der rechte Operand eines Member-Zugriffsoperators.
- Wenn E ein qualifizierter Bezeichner-Ausdruck ist, ist E nicht der ungeklammerte Operand eines Adressoperators.
- Eine der folgenden Bedingungen ist erfüllt
- E ist potenziell ausgewertet.
-
Cist die innerste umschließende Klasse bei E. -
Cist eine Basisklasse der innersten umschließenden Klasse bei E.
Diese Transformation gilt nicht im Kontext einer Template-Definition (siehe abhängige Namen).
struct X { int x; }; struct B { int b; }; struct D : B { X d; void func() { d; // OK, will be transformed into this->d b; // OK, will be transformed into this->b x; // Error: this->x is ill-formed d.x; // OK, will be transformed into this->d.x // instead of d.this->x or this->d.this->x } };
[bearbeiten] Namen
Ein Name ist die Verwendung einer der folgenden zur Benennung einer Entität
- ein Bezeichner
- ein Name für einen überladenen Operator in Funktionsnotation (operator+, operator new)
- ein Name für eine benutzerdefinierte Konvertierungsfunktion (operator bool)
|
(seit C++11) |
- ein Template-Name gefolgt von seiner Argumentliste (MyTemplate<int>)
Jeder Name wird durch eine Deklaration in das Programm eingeführt. Ein Name, der in mehr als einer Translation Unit verwendet wird, kann auf dieselben oder unterschiedliche Entitäten verweisen, abhängig von der Bindung.
Wenn der Compiler auf einen unbekannten Namen in einem Programm trifft, ordnet er ihn durch Namenssuche der Deklaration zu, die den Namen eingeführt hat, mit Ausnahme der abhängigen Namen in Template-Deklarationen und -Definitionen (für diese Namen ermittelt der Compiler, ob sie einen Typ, ein Template oder eine andere Entität benennen, was eine explizite Disambiguierung erfordern kann).
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 1440 | C++11 | decltype-Ausdrücke vor :: könnten jeden Typ bezeichnen |
können nur Klassen oder Aufzählungstypen bezeichnen |
| CWG 1963 | C++11 | implementierungsdefinierte Zeichen außer Ziffern, Nicht-Ziffern und universelle Zeichen-Namen könnten in einem Bezeichner verwendet werden |
verboten |
| CWG 2521 | C++11 | der Bezeichner in benutzerdefinierten Zeichenkettenliteralen von einem Literaloperator war wie üblich reserviert |
die Regeln sind anders |
| CWG 2771 | C++98 | &a wurde in Klassenkontexten nicht in &this->a umgewandelt | es wird umgewandelt |
| CWG 2777 | C++20 | der Typ eines Bezeichnerausdrucks war unklar wenn er einen Template-Parameter-Objektnamen bezeichnet |
wurde klargestellt |
| CWG 2818 | C++98 | vordefinierte Makronamen sind reserviert | sie sind nicht reserviert |
[bearbeiten] Siehe auch
| C-Dokumentation für Bezeichner
|