Expressions
Ein Ausdruck ist eine Sequenz von Operatoren und ihren Operanden , die eine Berechnung spezifiziert.
Die Auswertung von Ausdrücken kann ein Ergebnis erzeugen (z.B. ergibt die Auswertung von 2 + 2 das Ergebnis 4 ) und kann Nebeneffekte verursachen (z.B. gibt die Auswertung von std:: printf ( "%d" , 4 ) das Zeichen '4' auf die Standardausgabe aus).
Jeder C++-Ausdruck ist durch zwei unabhängige Eigenschaften gekennzeichnet: einen Typ und eine Wertkategorie.
Inhaltsverzeichnis |
Allgemein
- Wertkategorien (lvalue, rvalue , glvalue, prvalue, xvalue (seit C++11) ) klassifizieren Ausdrücke nach ihren Werten
- Auswertungsreihenfolge von Argumenten und Teilausdrücken spezifiziert die Reihenfolge, in der Zwischenergebnisse erhalten werden
Operatoren
| Häufig verwendete Operatoren | ||||||
|---|---|---|---|---|---|---|
| Zuweisung |
Inkrement
Dekrement |
Arithmetik | Logisch | Vergleich |
Member
Zugriff |
Sonstige |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
...
]
|
Funktionsaufruf
a ( ... ) |
|
Komma
a, b |
||||||
|
Bedingungsoperator
a ? b : c |
||||||
| Spezielle Operatoren | ||||||
|
static_cast
konvertiert einen Typ in einen anderen verwandten Typ
|
||||||
- Operator-Präzedenz definiert die Reihenfolge, in der Operatoren an ihre Argumente gebunden werden
- alternative Darstellungen sind alternative Schreibweisen für einige Operatoren
- Operator-Überladung ermöglicht es, das Verhalten der Operatoren mit benutzerdefinierten Klassen zu spezifizieren.
Konvertierungen
- Standardkonvertierungen implizite Konvertierungen von einem Typ zu einem anderen
-
const_castKonvertierung -
static_castKonvertierung -
dynamic_castKonvertierung -
reinterpret_castKonvertierung - explizite Konvertierung Konvertierung mittels C-Stil-Cast-Notation und Funktionsstil-Notation
- benutzerdefinierte Konvertierung ermöglicht die Spezifikation von Konvertierungen aus benutzerdefinierten Klassen
Speicherzuweisung
- new expression weist Speicher dynamisch zu
- delete expression gibt Speicher dynamisch frei
Sonstiges
- konstante Ausdrücke können zur Compilezeit ausgewertet werden und in Compilezeit-Kontexten verwendet werden (Template-Argumente, Array-Größen, etc.)
-
sizeof -
alignof -
typeid - throw-Ausdruck
Primäre Ausdrücke
Die Operanden jedes Operators können andere Ausdrücke oder primäre Ausdrücke sein (z.B. in 1 + 2 * 3 sind die Operanden des Operators+ der Teilausdruck 2 * 3 und der primäre Ausdruck 1 ).
Primäre Ausdrücke sind einer der Folgenden:
-
this - Literale (z.B. 2 oder "Hello, world" )
-
Identifikatorausdrücke, einschließlich
- geeignet deklarierter unqualifizierter Identifikatoren (z.B. n oder cout ),
- geeignet deklarierter qualifizierter Identifikatoren (z.B. std::string::npos ), und
- zu deklarierender Identifikatoren in Deklaratoren
| (seit C++26) |
| (seit C++11) | |
| (seit C++17) | |
| (seit C++20) |
Jeder Ausdruck in Klammern wird ebenfalls als primärer Ausdruck klassifiziert: Dies gewährleistet, dass die Klammern eine höhere Priorität als jeder Operator haben. Klammern bewahren Wert, Typ und Wertkategorie.
Literale
Literale sind die Tokens eines C++-Programms, die konstante Werte darstellen, die in den Quellcode eingebettet sind.
- Integer-Literale sind dezimale, oktale, hexadezimale oder binäre Zahlen ganzzahligen Typs.
- Zeichenliterale sind einzelne Zeichen des Typs
-
- char oder wchar_t
|
(seit C++11) |
|
(seit C++20) |
- Gleitkommaliterale sind Werte vom Typ float , double , oder long double
- Zeichenkettenliterale sind Zeichenfolgen vom Typ
-
- const char [ ] oder const wchar_t [ ]
|
(seit C++11) |
|
(seit C++20) |
- Boolesche Literale sind Werte vom Typ bool , also true und false
|
(seit C++11) |
Vollständige Ausdrücke
Ein Bestandteilsausdruck wird wie folgt definiert:
- Der konstituierende Ausdruck eines Ausdrucks ist dieser Ausdruck selbst.
- Die konstituierenden Ausdrücke einer geschweiften Klammer-Initialisierungsliste oder einer (möglicherweise in Klammern gesetzten) Ausdrucksliste sind die konstituierenden Ausdrücke der Elemente der jeweiligen Liste.
-
Die konstituierenden Ausdrücke eines
Initialisierers
, der mit
=beginnt, sind die konstituierenden Ausdrücke der Initialisierer-Klausel .
int num1 = 0; num1 += 1; // Fall 1: der konstituierende Ausdruck von "num += 1" ist "num += 1" int arr2[2] = {2, 22} // Fall 2: die konstituierenden Ausdrücke // von "{2, 22}" sind "2" und "22" // Fall 3: die konstituierenden Ausdrücke von "= {2, 22}" // sind die konstituierenden Ausdrücke von "{2, 22}" // (also ebenfalls "2" und "22")
Die unmittelbaren Teilausdrücke eines Ausdrucks E sind
- die Bestandteile der Ausdrücke von E s Operanden,
|
(seit C++14) |
|
(seit C++11) |
- jeden Funktionsaufruf, der E implizit aufruft, oder
- falls E ein Funktionsaufruf ist oder implizit eine Funktion aufruft, die Bestandteilsausdrücke jedes Standardarguments , das im Aufruf verwendet wird.
Ein Unterausdruck eines Ausdrucks E ist ein unmittelbarer Unterausdruck von E oder ein Unterausdruck eines unmittelbaren Unterausdrucks von E . Beachten Sie, dass Ausdrücke im "Funktionskörper" von Lambda-Ausdrücken keine Unterausdrücke des Lambda-Ausdrucks sind. (seit C++11)
Die folgenden Ausdrücke sind vollständige Ausdrücke :
| (seit C++20) |
- Deklaratoren von einfachen Deklarationen oder Member-Initialisierern , einschließlich der Bestandteile der Initialisierungsausdrücke
- Aufrufe von Destruktoren , die am Ende der Lebensdauer von Objekten generiert werden, außer temporärer Objekte, deren Lebensdauer nicht verlängert wurde
|
(seit C++26) |
- Ausdrücke, die kein Teilausdruck eines anderen Ausdrucks sind und die nicht Teil eines vollständigen Ausdrucks sind
Wenn ein Sprachkonstrukt definiert ist, um einen impliziten Aufruf einer Funktion zu erzeugen, gilt die Verwendung des Sprachkonstrukts als Ausdruck für die Zwecke dieser Definition. Konvertierungen, die auf das Ergebnis eines Ausdrucks angewendet werden, um die Anforderungen des Sprachkonstrukts zu erfüllen, in dem der Ausdruck erscheint, werden ebenfalls als Teil des vollständigen Ausdrucks betrachtet.
Für einen Initialisierer gilt die Durchführung der Initialisierung der Entität (einschließlich der Auswertung von Default-Member-Initialisierern eines Aggregats) (seit C++14) ebenfalls als Teil des vollständigen Ausdrucks.
Potenziell ausgewertete Ausdrücke
|
Ein Ausdruck wird potenziell ausgewertet , es sei denn
|
(bis C++11) | ||
|
Die folgenden Operanden sind nicht ausgewertete Operanden , sie werden nicht ausgewertet:
Ein Ausdruck wird potenziell ausgewertet , es sei denn
|
(seit C++11) |
Potentially-evaluierte Ausdrücke sind ODR-use .
|
Dieser Abschnitt ist unvollständig
Grund: Beispiel für nicht ausgewertete Operanden |
Verworfen-Wert-Ausdrücke
Ein discarded-value expression (verworfenen Wert-Ausdruck) ist ein Ausdruck, der nur für seine Nebeneffekte verwendet wird. Der von einem solchen Ausdruck berechnete Wert wird verworfen. Solche Ausdrücke umfassen den vollständigen Ausdruck jeder expression statement (Ausdrucksanweisung), den linken Operanden des eingebauten Komma-Operators oder den Operanden einer Cast-Expression, die zum Typ void konvertiert.
Array-zu-Pointer- und Function-zu-Pointer-Konvertierungen werden niemals auf den Wert angewendet, der durch einen discarded-value-Ausdruck berechnet wird. Die Lvalue-zu-Rvalue-Konvertierung wird genau dann angewendet, wenn der Ausdruck ein volatile-qualified Glvalue ist und eine der folgenden Formen hat (eingebaute Bedeutung erforderlich, möglicherweise in Klammern):
- ID-Ausdruck,
- Array-Index-Ausdruck,
- Klassen-Member-Zugriffsausdruck,
- Indirektion,
- Zeiger-auf-Member-Operation,
- Bedingter Ausdruck, bei dem sowohl der zweite als auch der dritte Operand einer dieser Ausdrücke ist,
- Komma-Ausdruck, bei dem der rechte Operand einer dieser Ausdrücke ist.
Zusätzlich, wenn der L-Wert vom flüchtig qualifizierten Klassentyp ist, wird ein flüchtiger Kopierkonstruktor benötigt, um den resultierenden R-Wert-Temporär zu initialisieren.
|
Wenn der Ausdruck ein Nicht-void-Prvalue ist (nach etwaiger Lvalue-zu-Rvalue-Konvertierung), erfolgt temporäre Materialisierung .
Compiler können Warnungen ausgeben, wenn ein Ausdruck außer einem Cast zu
void
einen Wert verwirft, der als
|
(since C++17) |
AusdrucksäquivalenzEine Anzahl von Ausdrücken e1 , e2 , ..., eN sind ausdrucksäquivalent wenn alle folgenden Bedingungen erfüllt sind:
e1 ist ausdrucksäquivalent zu e2 genau dann wenn e1 und e2 ausdrucksäquivalent sind (was bedeutet, dass e2 ebenfalls ausdrucksäquivalent zu e1 ist). |
(seit C++20) |
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 1054 | C++98 |
Das Zuweisen eines Werts zu einer volatile-Variable könnte
aufgrund der auf das Zuweisungsergebnis angewendeten Lvalue-zu-Rvalue-Konvertierung zu einem unnötigen Lesen führen |
Eingeführt von verworfenen Wertausdrücken
und diesen Fall von der Liste der Fälle ausgeschlossen, die die Konvertierung erfordern |
| CWG 1343 | C++98 |
Die Reihenfolge der Destruktoraufrufe bei
Aggregatinitialisierung war nicht ausreichend spezifiziert |
Vollausdrücke in der Aggregatinitialisierung
sind klar spezifiziert |
| CWG 1383 | C++98 |
Die Liste der Ausdrücke, bei denen Lvalue-zu-Rvalue-
Konvertierung auf verworfenen Wertausdrücken angewendet wird, umfasste auch überladene Operatoren |
Nur Operatoren mit eingebauter
Bedeutung abdecken |
| CWG 1576 | C++11 |
Lvalue-zu-Rvalue-Konvertierungen wurden nicht auf
verworfenen volatile-Xvalue-Ausdrücke angewendet |
Die Konvertierung in
diesem Fall anwenden |
| CWG 2249 | C++98 |
In Deklaratoren zu deklarierende Bezeichner
waren keine ID-Ausdrücke |
Sie sind es |
| CWG 2431 | C++11 |
Die Aufrufe der Destruktoren von Temporaries, die
an Referenzen gebunden sind, waren keine Vollausdrücke |
Sie sind es |
Siehe auch
|
C-Dokumentation
für
Ausdrücke
|