Andere Operatoren
| Operator name |
Syntax | Überladbar | Prototypenbeispiele (für class T) | |
|---|---|---|---|---|
| Innerhalb der Klassendefinition | Außerhalb der Klassendefinition | |||
| Funktionsaufruf | a(a1, a2)
|
Ja | R T::operator()(Arg1 &a1, Arg2 &a2, ...); | N/A |
| Komma | a, b
|
Ja | T2& T::operator,(T2 &b); | T2& operator,(const T &a, T2 &b); |
| bedingter Operator | a ? b : c
|
Nein | N/A | N/A |
Der Funktionsaufrufoperator stellt Funktionssemantik für jedes Objekt bereit.
Der bedingte Operator (umgangssprachlich als ternärer Konditionaloperator bezeichnet) prüft den booleschen Wert des ersten Ausdrucks und wertet je nach Ergebnis entweder den zweiten oder den dritten Ausdruck aus und gibt ihn zurück.
Inhalt |
[bearbeiten] Eingebauter Funktionsaufrufoperator
Funktionsaufrufausdrücke haben die folgende Form
function (arg1, arg2, arg3,...) |
|||||||||
| Funktion | - | ein Ausdruck vom Funktionstyp oder vom Zeigertyp auf eine Funktion |
arg1, arg2, arg3,... |
- | eine möglicherweise leere Liste beliebiger Ausdrücke oder mit geschweiften Klammern eingeschlossene Initialisierungslisten(seit C++11), wobei der Kommaoperator auf der obersten Ebene nicht zulässig ist, um Mehrdeutigkeit zu vermeiden |
Für einen Aufruf einer Nicht-Member-Funktion oder einer statischen Member-Funktion kann function ein lvalue sein, das auf eine Funktion verweist (in diesem Fall wird die Funktion-zu-Zeiger-Konvertierung unterdrückt), oder ein prvalue vom Zeigertyp auf eine Funktion.
Der durch function spezifizierte Funktions- (oder Member-)Name kann überladen sein; Überladungsregeln werden verwendet, um zu entscheiden, welche Überladung aufgerufen wird.
Wenn function eine Member-Funktion angibt, kann diese virtuell sein; in diesem Fall wird die endgültige Überschreiberin dieser Funktion aufgerufen, wobei dynamische Dispatch zur Laufzeit verwendet wird.
Jeder Funktionsparameter wird mit seinem entsprechenden Argument initialisiert, nach impliziter Konvertierung, falls erforderlich.
- Wenn kein entsprechendes Argument vorhanden ist, wird das entsprechende Standardargument verwendet. Wenn kein Standardargument vorhanden ist, ist das Programm schlecht geformt.
- Wenn der Aufruf einer Member-Funktion erfolgt, wird der this-Zeiger auf das aktuelle Objekt so konvertiert, als ob durch expliziten Cast auf den this-Zeiger, der von der Funktion erwartet wird.
- Die Initialisierung und Zerstörung jedes Parameters erfolgt im Kontext des vollständigen Ausdrucks, in dem der Funktionsaufruf erscheint. Das bedeutet zum Beispiel, dass, wenn ein Konstruktor oder Destruktor eines Parameters eine Ausnahme auslöst, die Funktions- try-Blöcke der aufgerufenen Funktion nicht berücksichtigt werden.
Wenn die Funktion eine variadische Funktion ist, werden auf alle durch den Ellipsis-Parameter abgeglichenen Argumente Standardargument-Promotions angewendet.
Ob ein Parameter zerstört wird, wenn die Funktion, in der er definiert ist, beendet wird, oder am Ende des umschließenden vollständigen Ausdrucks, ist implementierungsabhängig. Parameter werden immer in umgekehrter Reihenfolge ihrer Konstruktion zerstört.
Der Rückgabetyp eines Funktionsaufrufausdrucks ist der Rückgabetyp der ausgewählten Funktion, bestimmt durch statische Bindung (unter Ignorierung des virtual-Schlüsselworts), auch wenn die überschreibende Funktion, die tatsächlich aufgerufen wird, einen anderen Typ zurückgibt. Dies ermöglicht es den überschreibenden Funktionen, Zeiger oder Referenzen auf Klassen zurückzugeben, die von dem von der Basis-Funktion zurückgegebenen Rückgabetyp abgeleitet sind, d.h. C++ unterstützt kovariante Rückgabetypen. Wenn function einen Destruktor angibt, ist der Rückgabetyp void.
|
Wenn ein Objekt vom Klassentyp Das temporäre Objekt wird aus dem Funktionsargument bzw. dem Rückgabewert konstruiert, und der Parameter oder das Rückgabeobjekt der Funktion wird so initialisiert, als ob unter Verwendung des nicht gelöschten trivialen Konstruktors zum Kopieren des Temporären (auch wenn dieser Konstruktor unzugänglich ist oder bei der Überladungsauflösung nicht zur Durchführung einer Kopie oder Verschiebung des Objekts ausgewählt würde). Dies ermöglicht es Objekten kleiner Klassentypen, wie z.B. std::complex oder std::span, in Registern an Funktionen zu übergeben oder von ihnen zurückzugeben. |
(seit C++17) |
Die Wertkategorie eines Funktionsaufrufausdrucks ist ein lvalue, wenn die Funktion eine lvalue-Referenz oder eine rvalue-Referenz auf eine Funktion zurückgibt, ist ein xvalue, wenn die Funktion eine rvalue-Referenz auf ein Objekt zurückgibt, und ist andernfalls ein prvalue. Wenn der Funktionsaufrufausdruck ein prvalue vom Objekt-Typ ist, muss er einen unvollständigen Typ haben, es sei denn, er wird als Operand von decltype (oder als rechter Operand eines eingebauten Kommaoperators, der der Operand von decltype ist) verwendet(seit C++11).
|
Wenn die aufgerufene Funktion normal beendet wird, werden alle Nachbedingungsassertionen der Funktion in Sequenz ausgewertet. Wenn die Implementierung temporäre Objekte einführt, um den Ergebniswert zu speichern, für die Auswertung
|
(seit C++26) |
Der Funktionsaufrufausdruck ist syntaktisch ähnlich der Wertinitialisierung T(), dem funktionsähnlichen Cast-Ausdruck T(A1) und der direkten Initialisierung eines temporären Objekts T(A1, A2, A3, ...), wobei T der Name eines Typs ist.
#include <cstdio> struct S { int f1(double d) { return printf("%f \n", d); // variable argument function call } int f2() { return f1(7); // member function call, same as this->f1() // integer argument converted to double } }; void f() { puts("function called"); // function call } int main() { f(); // function call S s; s.f2(); // member function call }
Ausgabe
function called 7.000000
[bearbeiten] Eingebauter Kommaoperator
Kommaausdrücke haben die folgende Form
E1 , E2 |
|||||||||
In einem Kommaausdruck E1, E2 wird der Ausdruck E1 ausgewertet, sein Ergebnis wird verworfen (obwohl, wenn er einen Klassentyp hat, er nicht bis zum Ende des umschließenden vollständigen Ausdrucks zerstört wird), und seine Nebeneffekte werden abgeschlossen, bevor die Auswertung des Ausdrucks E2 beginnt (beachten Sie, dass ein benutzerdefinierter operator, keine Sequenzierung garantieren kann)(bis C++17).
Der Typ, der Wert und die Wertkategorie des Ergebnisses des Kommaausdrucks sind exakt der Typ, der Wert und die Wertkategorie des zweiten Operanden, E2. Wenn E2 ein temporärer Ausdruck(seit C++17) ist, ist das Ergebnis des Ausdrucks dieser temporäre Ausdruck(seit C++17). Wenn E2 ein Bitfeld ist, ist das Ergebnis ebenfalls ein Bitfeld.
Das Komma in verschiedenen durch Komma getrennten Listen, wie Funktionsargumentlisten (f(a, b, c)) und Initialisierungslisten int a[] = {1, 2, 3}, ist nicht der Kommaoperator. Wenn der Kommaoperator in solchen Kontexten verwendet werden muss, muss er in Klammern gesetzt werden: f(a, (n++, n + b), c).
|
Die Verwendung eines unparenthetisierten Kommaausdrucks als zweites (rechtes) Argument eines Indexoperators ist veraltet. Zum Beispiel ist a[b, c] veraltet und a[(b, c)] nicht. |
(seit C++20) (bis C++23) |
|
Ein unparenthetisierter Kommaausdruck kann nicht das zweite (rechte) Argument eines Indexoperators sein. Zum Beispiel ist a[b, c] entweder schlecht geformt oder äquivalent zu a.operator[](b, c). Klammern sind erforderlich, wenn ein Kommaausdruck als Index verwendet wird, z. B. a[(b, c)]. |
(seit C++23) |
#include <iostream> int main() { // comma is often used to execute more than one expression // where the language grammar allows only one expression: // * in the third component of the for loop for (int i = 0, j = 10; i <= j; ++i, --j) // ^list separator ^comma operator std::cout << "i = " << i << " j = " << j << '\n'; // * in a return statement // return log("an error!"), -1; // * in an initializer expression // MyClass(const Arg& arg) // : member{ throws_if_bad(arg), arg } // etc. // comma operators can be chained; the result of the last // (rightmost) expression is the result of the whole chain: int n = 1; int m = (++n, std::cout << "n = " << n << '\n', ++n, 2 * n); // m is now 6 std::cout << "m = " << (++m, m) << '\n'; }
Ausgabe
i = 0 j = 10 i = 1 j = 9 i = 2 j = 8 i = 3 j = 7 i = 4 j = 6 i = 5 j = 5 n = 2 m = 7
[bearbeiten] Bedingter Operator
Bedingte Operatorausdrücke haben die Form
E1 ? E2 : E3 |
|||||||||
E1 wird ausgewertet und kontextbezogen in bool konvertiert; wenn das Ergebnis true ist, ist das Ergebnis des bedingten Ausdrucks der Wert von E2; andernfalls ist das Ergebnis des bedingten Ausdrucks der Wert von E3.
Der Typ und die Wertkategorie des bedingten Ausdrucks E1 ? E2 : E3 werden wie folgt bestimmt
[bearbeiten] Stufe 1
Wenn sowohl E2 als auch E3 vom Typ void sind, ist das Ergebnis ein rvalue(bis C++11)ein prvalue(seit C++11) vom Typ void.
Wenn genau einer der Operanden E2 und E3 vom Typ void ist
- Wenn dieser Operand vom Typ void ein (möglicherweise in Klammern gesetzter) throw-Ausdruck ist, hat das Ergebnis den Typ und die Wertkategorie des anderen Operanden[1]. Wenn der andere Operand ein Bitfeld ist, ist das Ergebnis ebenfalls ein Bitfeld.
- Andernfalls ist das Programm fehlerhaft.
Wenn keiner der Operanden E2 und E3 vom Typ void ist, fahre mit der nächsten Stufe fort.
2 + 2 == 4 ? throw 123 : throw 456; // the result is of type “void” 2 + 2 != 4 ? "OK" : throw "error"; // the result is of type “const char[3]” // even if an exception is always thrown
[bearbeiten] Stufe 2
Wenn E2 oder E3 lvalue-Bitfelder(bis C++11)glvalue-Bitfelder mit derselben Wertkategorie(seit C++11) der Typen cv1 T bzw. cv2 T sind, werden die Operanden für den verbleibenden Prozess als vom Typ cv T betrachtet, wobei cv die Vereinigung von cv1 und cv2 ist.
Wenn E2 und E3 unterschiedliche Typen haben und eine der folgenden Bedingungen erfüllt ist, fahre mit Stufe 3 fort
- Mindestens einer der Operanden E2 und E3 ist ein (möglicherweise cv-qualifizierter) Klassentyp.
- Beide Operanden E2 und E3 sind lvalues desselben Typs(bis C++11)glvalues derselben Wertkategorie und desselben Typs(seit C++11), abgesehen von der cv-Qualifizierung.
Andernfalls fahre mit Stufe 4 fort.
[bearbeiten] Stufe 3
Es werden Versuche unternommen, eine implizite Konvertierungssequenz[2] von einem Operanden-Ausdruck X vom Typ TX zu einem Zieltyp zu bilden, der sich auf den Typ TY des Operanden-Ausdrucks Y bezieht, wie folgt
- Wenn Y ein lvalue ist, ist der Zieltyp
TY&, aber eine implizite Konvertierungssequenz kann nur gebildet werden, wenn die Referenz direkt an ein lvalue(bis C++11)ein glvalue(seit C++11) gebunden werden würde.
|
(seit C++11) |
- Wenn Y ein rvalue(bis C++11)ein prvalue(seit C++11) ist oder wenn keine der obigen Konvertierungssequenzen gebildet werden kann und mindestens einer der Typen
TXundTYein (möglicherweise cv-qualifizierter) Klassentyp ist- Wenn
TXundTYderselbe Klassentyp sind (unter Ignorierung von cv-Qualifizierungen)- Wenn
TYmindestens so cv-qualifiziert ist wieTX, ist der ZieltypTY. - Andernfalls wird keine Konvertierungssequenz gebildet.
- Wenn
- Andernfalls, wenn
TYeine Basisklasse vonTXist, ist der ZieltypTYmit den cv-Qualifizierern vonTX. - Andernfalls ist der Zieltyp der Typ von Z, wobei Z der Wert von Y nach Anwendung der lvalue-zu-rvalue-, Array-zu-Zeiger- und Funktion-zu-Zeiger-Standardkonvertierungen ist.
- Wenn
- Andernfalls wird keine Konvertierungssequenz gebildet.
Mithilfe dieses Prozesses wird bestimmt, ob eine implizite Konvertierungssequenz von E2 zum für E3 bestimmten Zieltyp gebildet werden kann und umgekehrt.
- Wenn keine Konvertierungssequenz gebildet werden kann, fahre mit der nächsten Stufe fort.
- Wenn genau eine Konvertierungssequenz gebildet werden kann
- Wenn die Konvertierungssequenz mehrdeutig ist, ist das Programm schlecht geformt.
- Andernfalls wird diese Konvertierung auf den ausgewählten Operanden angewendet und der konvertierte Operand wird anstelle des ursprünglichen Operanden für den verbleibenden Prozess verwendet, und fahre mit der nächsten Stufe fort.
- Wenn beide Sequenzen gebildet werden können, ist das Programm schlecht geformt.
struct A {}; struct B : A {}; using T = const B; A a = true ? A() : T(); // Y = A(), TY = A, X = T(), TX = const B, Target = const A
[bearbeiten] Stufe 4
|
Wenn E2 und E3 lvalues desselben Typs sind, ist das Ergebnis ein lvalue dieses Typs und ein Bitfeld, wenn mindestens einer von E2 und E3 ein Bitfeld ist. |
(bis C++11) |
|
Wenn E2 und E3 glvalues desselben Typs und derselben Wertkategorie sind, hat das Ergebnis denselben Typ und dieselbe Wertkategorie und ist ein Bitfeld, wenn mindestens einer von E2 und E3 ein Bitfeld ist. |
(seit C++11) |
Andernfalls ist das Ergebnis ein rvalue(bis C++11)ein prvalue(seit C++11).
- Wenn E2 und E3 nicht denselben Typ haben und einer davon ein (möglicherweise cv-qualifizierter) Klassentyp ist, fahre mit Stufe 5 fort.
- Andernfalls fahre mit Stufe 6 fort.
[bearbeiten] Stufe 5
Überladungsauflösung wird unter Verwendung der eingebauten Kandidaten durchgeführt, um zu versuchen, die Operanden in eingebaute Typen zu konvertieren.
- Wenn die Überladungsauflösung fehlschlägt, ist das Programm schlecht geformt.
- Andernfalls werden die ausgewählten Konvertierungen angewendet und die konvertierten Operanden werden anstelle der ursprünglichen Operanden für den verbleibenden Prozess verwendet. Fahre mit der nächsten Stufe fort.
[bearbeiten] Stufe 6
Die Array-zu-Zeiger- und Funktion-zu-Zeiger-Konvertierungen werden auf (möglicherweise konvertierte) E2 und E3 angewendet. Nach diesen Konvertierungen muss mindestens eine der folgenden Bedingungen erfüllt sein, andernfalls ist das Programm schlecht geformt
- E2 und E3 haben denselben Typ. In diesem Fall ist das Ergebnis von diesem Typ und das Ergebnis wird kopierinitialisiert unter Verwendung des ausgewählten Operanden.
- Beide E2 und E3 haben einen arithmetischen oder Enumerationstyp. In diesem Fall werden übliche arithmetische Konvertierungen angewendet, um sie in ihren gemeinsamen Typ zu bringen, und das Ergebnis ist von diesem Typ.
- Mindestens einer der Operanden E2 und E3 ist ein Zeiger. In diesem Fall werden lvalue-zu-rvalue-, Zeiger, Zeiger auf Funktion(seit C++17)- und Qualifizierungs-Konvertierungen angewendet, um sie in ihren zusammengesetzten Zeigertyp zu bringen, und das Ergebnis ist von diesem Typ.
- Mindestens einer der Operanden E2 und E3 ist ein Zeiger auf ein Member. In diesem Fall werden lvalue-zu-rvalue-, Zeiger-auf-Member, Zeiger auf Funktion(seit C++17)- und Qualifizierungs-Konvertierungen angewendet, um sie in ihren zusammengesetzten Zeigertyp zu bringen, und das Ergebnis ist von diesem Typ.
|
(seit C++11) |
int* intPtr; using Mixed = decltype(true ? nullptr : intPtr); static_assert(std::is_same_v<Mixed, int*>); // nullptr becoming int* struct A { int* m_ptr; } a; int* A::* memPtr = &A::m_ptr; // memPtr is a pointer to member m_ptr of A // memPtr makes nullptr as type of pointer to member m_ptr of A static_assert(std::is_same_v<decltype(false ? memPtr : nullptr), int*A::*>); // a.*memPtr is now just pointer to int and nullptr also becomes pointer to int static_assert(std::is_same_v<decltype(false ? a.*memPtr : nullptr), int*>);
- ↑ Ein solcher bedingter Operator wurde in C++11 constexpr-Programmierung vor C++14 häufig verwendet.
- ↑ Member-Zugriff, ob eine Konvertierungsfunktion gelöscht ist(seit C++11) und ob ein Operand ein Bitfeld ist, werden ignoriert.
|
Der Ergebnistyp eines bedingten Operators ist auch als binäre Typ-Eigenschaft std::common_type zugänglich. |
(seit C++11) |
[bearbeiten] Überladungen
Für jedes Paar von promotierten arithmetischen Typen L und R und für jeden Typ P, wobei P ein Zeiger-, Zeiger-auf-Member- oder ein gescopes Enumerationstyp ist, nehmen die folgenden Funktionssignaturen an der Überladungsauflösung teil
| LR operator?:(bool, L, R); |
||
| P operator?:(bool, P, P); |
||
wobei LR das Ergebnis der üblichen arithmetischen Konvertierungen ist, die auf L und R angewendet werden.
Der Operator „?:“ kann nicht überladen werden; diese Funktionssignaturen existieren nur zum Zweck der Überladungsauflösung.
#include <iostream> #include <string> struct Node { Node* next; int data; // deep-copying copy constructor Node(const Node& other) : next(other.next ? new Node(*other.next) : NULL) , data(other.data) {} Node(int d) : next(NULL), data(d) {} ~Node() { delete next; } }; int main() { // simple rvalue example int n = 1 > 2 ? 10 : 11; // 1 > 2 is false, so n = 11 // simple lvalue example int m = 10; (n == m ? n : m) = 7; // n == m is false, so m = 7 //output the result std::cout << "n = " << n << "\nm = " << m; }
Ausgabe
n = 11 m = 7
[bearbeiten] Standardbibliothek
Viele Klassen in der Standardbibliothek überladen operator(), um als Funktions-Objekte verwendet zu werden.
| löscht das Objekt oder Array (öffentliche Member-Funktion von std::default_delete<T>) | |
| gibt die Summe zweier Argumente zurück (öffentliche Member-Funktion von std::plus<T>) | |
| gibt die Differenz zwischen zwei Argumenten zurück (öffentliche Member-Funktion von std::minus<T>) | |
| gibt das Produkt zweier Argumente zurück (öffentliche Member-Funktion von std::multiplies<T>) | |
| gibt das Ergebnis der Division des ersten Arguments durch das zweite Argument zurück (öffentliche Member-Funktion von std::divides<T>) | |
| gibt den Rest aus der Division des ersten Arguments durch das zweite Argument zurück (öffentliche Member-Funktion von std::modulus<T>) | |
| gibt die Negation des Arguments zurück (öffentliche Member-Funktion von std::negate<T>) | |
| prüft, ob die Argumente gleich sind (öffentliche Member-Funktion von std::equal_to<T>) | |
| prüft, ob die Argumente nicht gleich sind (öffentliche Member-Funktion von std::not_equal_to<T>) | |
| prüft, ob das erste Argument größer als das zweite ist (öffentliche Member-Funktion von std::greater<T>) | |
| prüft, ob das erste Argument kleiner als das zweite ist (öffentliche Member-Funktion von std::less<T>) | |
| prüft, ob das erste Argument größer oder gleich dem zweiten ist (öffentliche Member-Funktion von std::greater_equal<T>) | |
| prüft, ob das erste Argument kleiner oder gleich dem zweiten ist (öffentliche Member-Funktion von std::less_equal<T>) | |
| gibt das logische AND der beiden Argumente zurück (öffentliche Member-Funktion von std::logical_and<T>) | |
| gibt das logische OR der beiden Argumente zurück (öffentliche Member-Funktion von std::logical_or<T>) | |
| gibt das logische NOT des Arguments zurück (öffentliche Member-Funktion von std::logical_not<T>) | |
| gibt das Ergebnis des bitweisen AND zweier Argumente zurück (öffentliche Member-Funktion von std::bit_and<T>) | |
| gibt das Ergebnis des bitweisen OR zweier Argumente zurück (öffentliche Member-Funktion von std::bit_or<T>) | |
| gibt das Ergebnis des bitweisen XOR zweier Argumente zurück (öffentliche Member-Funktion von std::bit_xor<T>) | |
| gibt das logische Komplement des Ergebnisses eines Aufrufs des gespeicherten Prädikats zurück (öffentliche Member-Funktion von std::unary_negate<Predicate>) | |
| gibt das logische Komplement des Ergebnisses eines Aufrufs des gespeicherten Prädikats zurück (öffentliche Member-Funktion von std::binary_negate<Predicate>) | |
| ruft die gespeicherte Funktion auf (öffentliche Member-Funktion von std::reference_wrapper<T>) | |
| ruft das Ziel auf (public member function of std::function<R(Args...)>) | |
| ruft das Ziel auf (public member function of std::move_only_function) | |
| ruft das Ziel auf (öffentliche Member-Funktion von std::copyable_function) | |
| setzt die Ausführung der Coroutine fort (öffentliche Member-Funktion von std::coroutine_handle<Promise>) | |
| Vergleicht lexikografisch zwei Zeichenketten mit der collate-Facet dieses Locales. (public member function of std::locale) | |
Vergleicht zwei Werte vom Typ value_type(öffentliche Member-Funktion von std::map<Key,T,Compare,Allocator>::value_compare) | |
Vergleicht zwei Werte vom Typ value_type(öffentliche Member-Funktion von std::multimap<Key,T,Compare,Allocator>::value_compare) | |
| führt die Funktion aus (öffentliche Member-Funktion von std::packaged_task<R(Args...)>) | |
| verschiebt den Zustand der Engine und gibt den generierten Wert zurück (öffentliche Member-Funktion von std::linear_congruential_engine<UIntType,a,c,m>) | |
| (C++11) |
erzeugt die nächste Zufallszahl in der Verteilung (öffentliche Memberfunktion von std::uniform_int_distribution<IntType>) |
Der Komma-Operator wird von keiner Klasse in der Standardbibliothek überladen. Die Boost-Bibliothek verwendet operator, in boost.assign, boost.spirit und anderen Bibliotheken. Die Datenbankzugriffsbibliothek SOCI überlädt ebenfalls operator,.
[bearbeiten] Defect reports
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 446 | C++98 | Es war nicht spezifiziert, ob für eine lvalue-zu-rvalue-Konvertierung beim bedingten Operator |
immer ein temporäres Objekt erstellt wird, wenn der Operator einen Klassen-rvalue zurückgibt |
| CWG 462 | C++98 | Wenn der zweite Operand eines Komma-Operators ein temporäres Objekt ist, war nicht spezifiziert, ob seine Lebensdauer verlängert wird, wenn das Ergebnis des Komma-Ausdrucks an eine Referenz gebunden wird |
das Ergebnis des Komma-Ausdrucks ist in diesem Fall das temporäre Objekt (daher wird seine Lebensdauer verlängert) |
| CWG 587 | C++98 | Wenn die zweiten und dritten Operanden eines bedingten Operators lvalues desselben Typs sind, außer bei cv-Qualifikation, war das Ergebnis ein lvalue, wenn diese Operanden Klassentypen haben, ansonsten ein rvalue |
das Ergebnis ist in diesem Fall immer ein lvalue |
| CWG 1029 | C++98 | Der Typ eines Destruktoraufrufs war nicht spezifiziert | spezifiziert als void |
| CWG 1550 | C++98 | In Klammern gesetzte throw-Ausdrücke waren in bedingten Ausdrücken nicht erlaubt, wenn der andere Operand kein void war |
akzeptiert |
| CWG 1560 | C++98 | void-Operand von bedingten Operatoren verursachte unnötige lvalue-zu-rvalue-Konvertierung auf dem anderen Operanden, was immer zu einem rvalue führte |
ein bedingter Ausdruck mit einem void kann ein lvalue sein |
| CWG 1642 | C++98 | der Ausdruck function in einem Funktionsaufruf Ausdruck konnte ein Funktionszeiger-lvalue sein |
nicht erlaubt |
| CWG 1805 | C++98 | Bei der Bestimmung des Zieltyps für die implizite Konvertierungssequenz war die Art und Weise, wie Y in Z konvertiert wird, unklar |
wurde klargestellt |
| CWG 1895 | C++98 C++11 |
unklar, ob eine gelöschte (C++11) oder unzugängliche (C++98) Konvertierungsfunktion die Konvertierung in bedingten Ausdrücken verhindert, und Konvertierungen von Basis- klassen zu abgeleiteten Klassen-prvalues wurden nicht berücksichtigt |
behandelt wie Overload Resolution |
| CWG 1932 | C++98 | Gleichheits-Bitfelder fehlten in bedingten Ausdrücken | behandelt durch zugrundeliegende Typen |
| CWG 2226 | C++11 | Bei der Bestimmung des Zieltyps des anderen Operanden eines bedingten Operators konnte eine Referenz nicht an ein xvalue gebunden werden, wenn dieser Operand ein lvalue war |
erlaubt |
| CWG 2283 | C++17 | Die Typvollständigkeitsanforderung für Funktionsaufrufe Operator wurde versehentlich durch P0135R1 entfernt |
die Anforderung wiederhergestellt |
| CWG 2321 | C++98 | Bei der Bestimmung des Zieltyps des anderen Operanden eines bedingten Operators konnte ein abgeleiteter Klassentyp nicht in eine weniger cv-qualifizierte Basisklasse konvertiert werden |
konnte in die Basis konvertiert werden Klasse mit der cv-Qualifikation vom abgeleiteten Klassenoperanden |
| CWG 2715 | C++98 | Die Initialisierung und Zerstörung jedes Parameters würde im Kontext von der aufrufenden Funktion stattfinden, die möglicherweise nicht existiert[1] |
findet im Kontext von dem umschließenden vollständigen Ausdruck statt |
| CWG 2850 | C++98 | Die Zerstörungsreihenfolge der Parameter war unklar | wurde klargestellt |
| CWG 2865 | C++98 | Wenn TX und TY derselbe Klassentyp sind und TXmehr cv-qualifiziert ist als TY, konnte immer noch eine implizite Konvertierungssequenz gebildet werden von einem prvalue Yes wird immer noch eine implizite Konvertierungssequenz gebildet von einem prvalue Y |
keine Konvertierungssequenz wird in diesem Fall gebildet |
| CWG 2906 | C++98 | lvalue-zu-rvalue-Konvertierungen wurden bedingungslos angewendet im rvalue-Ergebnis-Fall für den bedingten Operator |
nur in einigen Fällen angewendet |
- ↑ Zum Beispiel können Funktionen im Initialisierer einer Namespace-Scope-Variable aufgerufen werden, in diesem Kontext gibt es keine „aufrufende Funktion“.
[bearbeiten] Siehe auch
Operatorrangfolge
Operatorüberladung
| Häufige Operatoren | ||||||
|---|---|---|---|---|---|---|
| Zuweisung | Inkrement Dekrement |
Arithmetik | Logisch | Vergleich | Member Zugriff |
Sonstiges |
|
a = b |
++a |
+a |
!a |
a == b |
a[...] |
Funktionsaufruf a(...) |
| Komma a, b | ||||||
| Ternär a ? b : c | ||||||
| Spezielle Operatoren | ||||||
|
static_cast konvertiert einen Typ in einen anderen verwandten Typ | ||||||
| C-Dokumentation für Andere Operatoren
|