Namespaces
Variants

Type

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

Objekte , Referenzen , Funktionen einschließlich Funktions-Templatespezialisierungen , und Ausdrücke haben eine Eigenschaft namens Typ , die sowohl die Operationen einschränkt, die für diese Entitäten erlaubt sind, als auch semantische Bedeutung für die ansonsten generischen Bitsequenzen bereitstellt.

Inhaltsverzeichnis

Typklassifizierung

Das C++-Typsystem besteht aus den folgenden Typen:

(seit C++11)
  • der Typ bool ;
  • Zeichentypen:
  • Schmale Zeichentypen:
  • Gewöhnliche Zeichentypen: char , signed char , unsigned char [1]
  • der Typ char8_t
(seit C++20)
  • Breitzeichen-Typen: char16_t , char32_t , (seit C++11) wchar_t ;
  • Ganzzahltypen mit Vorzeichen:
  • Standard-Ganzzahltypen mit Vorzeichen: signed char , short , int , long , long long ;
  • erweiterte vorzeichenbehaftete Ganzzahltypen (implementierungsdefiniert);
(since C++11)
  • vorzeichenlose Ganzzahltypen:
  • Standard vorzeichenlose Ganzzahltypen: unsigned char , unsigned short , unsigned , unsigned long , unsigned long long ;
  • erweiterte vorzeichenlose Ganzzahltypen (jeder entspricht einem erweiterten vorzeichenbehafteten Ganzzahltyp und umgekehrt);
(seit C++11)
(seit C++23)
  • Lvalue-Referenz auf Objekttypen;
  • Lvalue-Referenz auf Funktionstypen;
  • Rvalue-Referenz auf Objekttypen;
  • Rvalue-Referenz auf Funktionstypen;
(seit C++11)
(seit C++11)
  1. signed char und unsigned char sind Narrow-Character-Typen, aber sie sind keine Character-Typen. Mit anderen Worten: Die Menge der Narrow-Character-Typen ist keine Teilmenge der Menge der Character-Typen.

Für jeden nicht-cv-qualifizierten Typ, außer Referenz- und Funktionstypen, unterstützt das Typsystem drei zusätzliche cv-qualifizierte Versionen dieses Typs ( const , volatile , und const volatile ).

Weitere Kategorien

Ein Objekttyp (siehe auch std::is_object ) ist ein (möglicherweise cv-qualifizierter) Typ, der kein Funktionstyp, kein Referenztyp und kein (möglicherweise cv-qualifizierter) void ist.

Die folgenden Typen werden zusammen als Skalartypen bezeichnet (siehe auch std::is_scalar ):

(seit C++11)
  • cv-qualifizierte Versionen dieser Typen

Die folgenden Typen werden zusammen als implicit-lifetime types bezeichnet:

Die folgenden Typen werden zusammenfassend als trivial kopierbare Typen bezeichnet:

Die folgenden Typen werden zusammenfassend als Standard-Layout-Typen bezeichnet:

(since C++11)

Diagramm der Type-Traits-Hierarchie

cpp types v3.svg

Hinweis: Elemente des SVG-Bildes sind anklickbar, aber Sie müssen das Diagramm zuerst in einem neuen Browser-Tab öffnen

Veraltete Kategorien

Die folgenden Typen werden zusammen als POD-Typen bezeichnet (siehe auch std::is_pod ):

  • skalare Typen
  • POD-Klassen
  • Arrays solcher Typen
  • cv-qualifizierte Versionen dieser Typen
(in C++20 veraltet)

Die folgenden Typen werden zusammen als triviale Typen bezeichnet (siehe auch std::is_trivial ):

(seit C++11)
(in C++26 veraltet)

Programmdatentyp

Eine programmdefinierte Spezialisierung ist eine explizite Spezialisierung oder partielle Spezialisierung , die nicht Teil der C++ Standardbibliothek ist und nicht durch die Implementierung definiert wird.

Ein programmdefinierter Typ ist einer der folgenden Typen:

(since C++11)

Typbenennung

Ein Name kann deklariert werden, um auf einen Typ zu verweisen, mittels:

Typen, die keine Namen haben, müssen oft in C++-Programmen referenziert werden; die Syntax dafür ist bekannt als type-id . Die Syntax der type-id, die den Typ T benennt, ist exakt die Syntax einer Deklaration einer Variable oder Funktion vom Typ T , wobei der Identifikator weggelassen wird, mit der Ausnahme, dass decl-specifier-seq der Deklarationsgrammatik auf type-specifier-seq beschränkt ist, und dass neue Typen nur definiert werden dürfen, wenn die type-id auf der rechten Seite einer Nicht-Template-Typalias-Deklaration erscheint.

int* p;               // Deklaration eines Zeigers auf int
static_cast<int*>(p); // type-id ist "int*"
int a[3];   // Deklaration eines Arrays von 3 int
new int[3]; // type-id ist "int[3]" (genannt new-type-id)
int (*(*x[2])())[3];      // Deklaration eines Arrays von 2 Zeigern auf Funktionen
                          // die Zeiger auf Arrays von 3 int zurückgeben
new (int (*(*[2])())[3]); // type-id ist "int (*(*[2])())[3]"
void f(int);                    // Deklaration einer Funktion, die int nimmt und void zurückgibt
std::function<void(int)> x = f; // Typ-Template-Parameter ist eine type-id "void(int)"
std::function<auto(int) -> void> y = f; // dasselbe
std::vector<int> v;       // Deklaration eines Vektors von int
sizeof(std::vector<int>); // type-id ist "std::vector<int>"
struct { int x; } b;         // erzeugt einen neuen Typ und deklariert ein Objekt b dieses Typs
sizeof(struct { int x; });   // Fehler: Neue Typen können nicht in sizeof-Ausdrücken definiert werden
using t = struct { int x; }; // erzeugt einen neuen Typ und deklariert t als Alias dieses Typs
sizeof(static int); // Fehler: Speicherklassenspezifizierer sind nicht Teil der type-specifier-seq
std::function<inline void(int)> f; // Fehler: ebenso wenig sind Funktionsspezifizierer erlaubt

Der Deklarator -Teil der Deklarationsgrammatik ohne den Namen wird als abstrakter Deklarator bezeichnet.

Type-id kann in den folgenden Situationen verwendet werden:

(bis C++17)

Type-id kann mit einigen Modifikationen in den folgenden Situationen verwendet werden:

  • in der Parameterliste einer Funktion (wenn der Parametername weggelassen wird), verwendet type-id decl-specifier-seq anstelle von type-specifier-seq (insbesondere sind einige Speicherklassenspezifizierer erlaubt);
  • im Namen einer benutzerdefinierten Konvertierungsfunktion , kann der abstrakte Deklarator keine Funktions- oder Arrayoperatoren enthalten.

Elaborierte Typspezifizierer

Ausgeführte Typspezifizierer können verwendet werden, um auf einen zuvor deklarierten Klassennamen (class, struct oder union) oder einen zuvor deklarierten Enum-Namen zu verweisen, selbst wenn der Name durch eine Nicht-Typ-Deklaration verborgen wurde . Sie können auch verwendet werden, um neue Klassennamen zu deklarieren.

Siehe elaborated type specifier für Details.

Statischer Typ

Der Typ eines Ausdrucks, der sich aus der Compilezeit-Analyse des Programms ergibt, wird als static type des Ausdrucks bezeichnet. Der static type ändert sich nicht während der Programmausführung.

Dynamischer Typ

Wenn ein glvalue expression auf ein polymorphic object verweist, wird der Typ seines am stärksten abgeleiteten Objekts als der dynamische Typ bezeichnet.

// gegeben
struct B { virtual ~B() {} }; // polymorpher Typ
struct D : B {};               // polymorpher Typ
D d; // abgeleitetstes Objekt
B* ptr = &d;
// der statische Typ von (*ptr) ist B
// der dynamische Typ von (*ptr) ist D

Für prvalue-Ausdrücke ist der dynamische Typ immer derselbe wie der statische Typ.

Unvollständiger Typ

Die folgenden Typen sind unvollständige Typen :

Alle anderen Typen sind vollständig.

Jeder der folgenden Kontexte erfordert, dass der Typ T vollständig ist:

(Im Allgemeinen, wenn die Größe und das Layout von T bekannt sein müssen.)

Wenn eine dieser Situationen in einer Übersetzungseinheit auftritt, muss die Definition des Typs in derselben Übersetzungseinheit erscheinen. Andernfalls ist sie nicht erforderlich.

Ein unvollständig definierter Objekttyp kann vervollständigt werden:

  • Ein Klassentyp (wie class X ) kann an einer Stelle einer Übersetzungseinheit als unvollständig betrachtet werden und später als vollständig; der Typ class X ist an beiden Stellen derselbe Typ:
struct X;            // Deklaration von X, noch keine Definition vorhanden
extern X* xp;        // xp ist ein Zeiger auf einen unvollständigen Typ:
                     // die Definition von X ist nicht erreichbar
void foo()
{
    xp++;            // unzulässig: X ist unvollständig
}
struct X { int i; }; // Definition von X
X x;                 // OK: die Definition von X ist erreichbar
void bar()
{
    xp = &x;         // OK: Typ ist "Zeiger auf X"
    xp++;            // OK: X ist vollständig
}
  • Der deklarierte Typ eines Array-Objekts kann ein Array von unvollständigem Klassentyp sein und daher unvollständig; wenn der Klassentyp später in der Übersetzungseinheit vervollständigt wird, wird der Array-Typ vollständig; der Array-Typ an diesen beiden Punkten ist derselbe Typ.
  • Der deklarierte Typ eines Array-Objekts kann ein Array mit unbekannter Grenze sein und daher an einem Punkt in einer Übersetzungseinheit unvollständig und später vollständig sein; die Array-Typen an diesen beiden Punkten ("Array mit unbekannter Grenze von T " und "Array von N T ") sind unterschiedliche Typen.

Der Typ eines Zeigers oder einer Referenz auf ein Array unbekannter Größe zeigt permanent auf oder bezieht sich permanent auf einen unvollständigen Typ. Ein Array unbekannter Größe, das durch eine typedef -Deklaration benannt wird, bezieht sich permanent auf einen unvollständigen Typ. In beiden Fällen kann der Array-Typ nicht vervollständigt werden:

extern int arr[];   // der Typ von arr ist unvollständig
typedef int UNKA[]; // UNKA ist ein unvollständiger Typ
UNKA* arrp;         // arrp ist ein Zeiger auf einen unvollständigen Typ
UNKA** arrpp;
void foo()
{
    arrp++;         // Fehler: UNKA ist ein unvollständiger Typ
    arrpp++;        // OK: sizeof UNKA* ist bekannt
}
int arr[10];        // jetzt ist der Typ von arr vollständig
void bar()
{
    arrp = &arr;    // OK: Qualifikationskonvertierung (seit C++20)
    arrp++;         // Fehler: UNKA kann nicht vervollständigt werden
}

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 328 C++98 Klassenmitglieder von unvollständigem Typ waren nicht verboten
falls ein Objekt des Klassentyps nie erzeugt wurde
nicht-statische Klassendatenmitglieder
müssen vollständig sein
CWG 977 C++98 der Zeitpunkt, zu dem ein Aufzählungstyp in seiner Definition
vollständig wird, war unklar
der Typ ist vollständig, sobald der
zugrundeliegende Typ bestimmt ist
CWG 1362 C++98 benutzerdefinierte Konvertierungen zu Typ T* oder T& erforderten T vollständig nicht erforderlich
CWG 2006 C++98 cv-qualifizierte void Typen waren Objekttyp und vollständiger Typ von beiden Kategorien ausgeschlossen
CWG 2448 C++98 nur cv-unqualifizierte Typen konnten Integral- und Gleitkommatypen sein erlaubt cv-qualifizierte Typen
CWG 2630 C++98 es war unklar, ob eine Klasse außerhalb der Übersetzungseinheit,
in der die Definition der Klasse erscheint, als vollständig gilt
die Klasse ist vollständig,
wenn ihre Definition in diesem Fall
erreichbar ist
CWG 2643 C++98 der Typ eines Zeigers auf Array unbekannter Größe
konnte nicht vervollständigt werden (aber er ist bereits vollständig)
der gezeigte Array-Typ
kann nicht vervollständigt werden
LWG 2139 C++98 die Bedeutung von "benutzerdefiniertem Typ" war unklar definiert und verwendet "programm-
definierter Typ" stattdessen
LWG 3119 C++11 es war unklar, ob Closure-Typen programm-definierte Typen sind klargestellt

Referenzen

  • C++23-Standard (ISO/IEC 14882:2024):
  • 6.8.2 Fundamentale Typen [basic.fundamental]
  • C++20-Standard (ISO/IEC 14882:2020):
  • 6.8.2 Fundamentale Typen [basic.fundamental]
  • C++17-Standard (ISO/IEC 14882:2017):
  • 6.9.1 Fundamentale Typen [basic.fundamental]
  • C++14-Standard (ISO/IEC 14882:2014):
  • 3.9.1 Fundamentale Typen [basic.fundamental]
  • C++11-Standard (ISO/IEC 14882:2011):
  • 3.9.1 Fundamentale Typen [basic.fundamental]
  • C++98-Standard (ISO/IEC 14882:1998):
  • 3.9.1 Fundamentale Typen [basic.fundamental]

Siehe auch

Type traits Eine template-basierte Schnittstelle zur Übersetzungszeit zum Abfragen der Eigenschaften von Typen

Externe Links

1. Howard Hinnants C++0x-Typenbaum