Namensräume
Varianten
Aktionen

Bezeichner

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

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.
  • Der einzige Ort, an dem sie als Nicht-Schlüsselwörter verwendet werden können, ist in einem Attribut-Token (z. B. [[private]] ist ein gültiges Attribut).
(seit C++11)
  • Die Bezeichner, die alternative Darstellungen für bestimmte Operatoren und Satzzeichen sind, dürfen nicht für andere Zwecke verwendet werden.
  • Die Bezeichner mit Sonderbedeutung (final, import, module(seit C++20) und override) werden explizit in einem bestimmten Kontext verwendet und sind keine regulären Bezeichner.
    • Sofern nicht anders angegeben, wird jede Mehrdeutigkeit bezüglich der Sonderbedeutung eines Bezeichners so aufgelöst, dass das Token als regulärer Bezeichner interpretiert wird.
(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
(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 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

  • Wenn die durch den (unqualifizierten) Bezeichner benannte Entität eine lokale Entität ist und außerhalb eines nicht ausgewerteten Operanden in der Deklarationsregion, in der der Bezeichner auftritt, durch Kopie erfasst würde, würde dies zu einem zwischengeschalteten Lambda-Ausdruck führen, dann ist der Typ des Ausdrucks der Typ eines Klassenmember-Zugriffs-Ausdrucks, der auf den nicht-statischen Datenmember verweist, der für eine solche Erfassung im Closure-Objekt des innersten solchen zwischengeschalteten Lambda-Ausdrucks deklariert 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, ist der Typ des Ausdrucks const T.
(seit C++20)
(seit C++11)

[bearbeiten] Unqualifizierte Bezeichner

Neben ordnungsgemäß deklarierten Bezeichnern können die folgenden in Ausdrücken in derselben Rolle verwendet werden

(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.
  • C ist die innerste umschließende Klasse bei E.
  • C ist 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)
  • ein Name für einen benutzerdefinierten Literaloperator (operator ""_km)
(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