return-Anweisung
Beendet die aktuelle Funktion und gibt den angegebenen Wert (falls vorhanden) an den Aufrufer zurück.
Inhalt |
[bearbeiten] Syntax
attr (optional) return expression (optional) ; |
(1) | ||||||||
attr (optional) return braced-init-list ; |
(2) | (seit C++11) | |||||||
attr (optional) co_return expression (optional) ; |
(3) | (seit C++20) | |||||||
attr (optional) co_return braced-init-list ; |
(4) | (seit C++20) | |||||||
| attr | - | (seit C++11) Sequenz einer beliebigen Anzahl von Attributen |
| expression | - | Ausdruck, konvertierbar in den Rückgabetyp der Funktion |
| Initialisierungsliste in geschweiften Klammern | - | in geschweifte Klammern eingeschlossene Initialisierungsliste |
[bearbeiten] Erklärung
|
Es gibt einen Sequenzpunkt zwischen der Kopierinitialisierung des Ergebnisses des Funktionsaufrufs und der Zerstörung aller temporären Objekte am Ende des Ausdrucks. |
(bis C++11) |
|
Die Kopierinitialisierung des Ergebnisses des Funktionsaufrufs ist sequenziert vor der Zerstörung aller temporären Objekte am Ende des Ausdrucks, was wiederum sequenziert vor der Zerstörung lokaler Variablen des die return-Anweisung umschließenden Blocks ist. |
(seit C++11) |
|
Wenn der Rückgabetyp der Funktion ein Referenztyp ist und eine return-Anweisung (1,2) die zurückgegebene Referenz an das Ergebnis eines temporären Ausdrucks bindet, ist das Programm ill-formed. |
(seit C++26) |
Wenn die Kontrolle das Ende von
- einer Funktion mit dem Rückgabetyp (möglicherweise cv-qualifiziert) void,
- einem Konstruktor,
- einem Destruktor oder
- einem Funktions-try-Block für eine Funktion mit dem Rückgabetyp (möglicherweise cv-qualifiziert) void
ohne eine return-Anweisung erreicht, wird return; ausgeführt.
Wenn die Kontrolle das Ende der main-Funktion erreicht, wird return 0; ausgeführt.
Das Auslaufen vom Ende einer wertrückgebenden Funktion, ausgenommen der main-Funktion und spezifischer Coroutinen(seit C++20), ohne eine return-Anweisung ist undefiniertes Verhalten.
In einer Funktion, die (möglicherweise cv-qualifiziertes) void zurückgibt, kann die return-Anweisung mit Ausdruck verwendet werden, wenn der Ausdruckstyp (möglicherweise cv-qualifiziertes) void ist.
|
Wenn der Rückgabetyp einer Funktion als Platzhaltertyp angegeben ist, wird dieser aus dem Rückgabewert deduziert. |
(seit C++14) |
[bearbeiten] Hinweise
Die Rückgabe per Wert kann die Konstruktion und das Kopieren/Verschieben eines temporären Objekts beinhalten, es sei denn, Kopierelision wird verwendet. Insbesondere sind die Bedingungen für das Kopieren/Verschieben wie folgt:
Automatisches Verschieben lokaler Variablen und ParameterDer Ausdruck ist verschiebbar, wenn er ein (möglicherweise in Klammern gesetzter) Bezeichnerausdruck ist, der eine Variable mit automatischer Speicherungsdauer benennt, deren Typ
|
(seit C++11) |
|
(seit C++20) |
|
und diese Variable deklariert ist
der innersten umschließenden Funktion oder Lambda-Ausdrucks. |
(seit C++11) |
|
Wenn der Ausdruck verschiebbar ist, wird die Überladungsauflösung zur Auswahl des zu verwendenden Konstruktors für die Initialisierung des zurückgegebenen Werts oder, für co_return, zur Auswahl der Überladung von promise.return_value()(seit C++20) zweimal durchgeführt:
|
(seit C++11) (bis C++23) |
|
(seit C++11) (bis C++20) |
|
(seit C++11) (bis C++23) |
|
Wenn der Ausdruck verschiebbar ist, wird er als xvalue behandelt (wodurch die Überladungsauflösung den Move-Konstruktor auswählen kann). |
(seit C++23) |
Garantierte KopierelisionWenn expression ein prvalue ist, wird das Objekt das Ergebnis direkt von diesem Ausdruck initialisiert. Dies beinhaltet keinen Kopier- oder Move-Konstruktor, wenn die Typen übereinstimmen (siehe Kopierelision). |
(seit C++17) |
| Feature-Testmakro | Wert | Std | Feature |
|---|---|---|---|
__cpp_implicit_move |
202207L |
(C++23) | Einfacheres implizites Verschieben |
[bearbeiten] Schlüsselwörter
[bearbeiten] Beispiel
#include <iostream> #include <string> #include <utility> void fa(int i) { if (i == 2) return; std::cout << "fa("<< i << ")\n"; } // implied return; int fb(int i) { if (i > 4) return 4; std::cout << "fb(" << i << ")\n"; return 2; } std::pair<std::string, int> fc(const char* p, int x) { return {p, x}; } void fd() { return fa(10); // fa(10) is a void expression } int main() { fa(1); // prints its argument, then returns fa(2); // does nothing when i == 2, just returns int i = fb(5); // returns 4 i = fb(i); // prints its argument, returns 2 std::cout << "i = " << i << '\n' << "fc(~).second = " << fc("Hello", 7).second << '\n'; fd(); } struct MoveOnly { MoveOnly() = default; MoveOnly(MoveOnly&&) = default; }; MoveOnly move_11(MoveOnly arg) { return arg; // OK. implicit move } MoveOnly move_11(MoveOnly&& arg) { return arg; // OK since C++20. implicit move } MoveOnly&& move_23(MoveOnly&& arg) { return arg; // OK since C++23. implicit move }
Ausgabe
fa(1) fb(4) i = 2 fc(~).second = 7 fa(10)
[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 1541 | C++98 | expression konnte nicht weggelassen werden, wenn der Rückgabetyp cv-qualifiziertes void war | kann weggelassen werden |
| CWG 1579 | C++11 | Rückgabe über konvertierenden Move-Konstruktor war nicht erlaubt | konvertierendes Verschieben Konstruktor-Lookup aktiviert |
| CWG 1885 | C++98 | Sequenzierung der Zerstörung von automatischen Variablen war nicht explizit | Sequenzierungsregeln hinzugefügt |
[bearbeiten] Siehe auch
| C-Dokumentation für
return-Anweisung |