Namensräume
Varianten
Aktionen

return-Anweisung

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
goto - return
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
 
 

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

1) Wertet den Ausdruck aus, beendet die aktuelle Funktion und gibt das Ergebnis des Ausdrucks an den Aufrufer zurück, nach impliziter Konvertierung in den Rückgabetyp der Funktion. Der Ausdruck ist optional in Funktionen, deren Rückgabetyp (möglicherweise cv-qualifiziert) void ist, und nicht zulässig in Konstruktoren und Destruktoren.
2) Verwendet Kopier-Listen-Initialisierung, um den Rückgabewert der Funktion zu konstruieren.
3,4) In einer Coroutine muss das Schlüsselwort co_return anstelle von return für den letzten Suspendierungspunkt verwendet werden (siehe Coroutinen für Details).

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 Parameter

Der Ausdruck ist verschiebbar, wenn er ein (möglicherweise in Klammern gesetzter) Bezeichnerausdruck ist, der eine Variable mit automatischer Speicherungsdauer benennt, deren Typ

  • ein nicht-volatiler Objekttyp
(seit C++11)
  • oder ein nicht-volatiler rvalue-Referenztyp zu einem Objekttyp ist
(seit C++20)

und diese Variable deklariert ist

  • im Körper
  • oder als Parameter

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:

  • zuerst so, als wäre der Ausdruck ein rvalue-Ausdruck (wodurch der Move-Konstruktor ausgewählt werden könnte), und
  • wenn die erste Überladungsauflösung fehlschlug
(seit C++11)
(bis C++23)
  • oder sie erfolgreich war, aber nicht den Move-Konstruktor auswählte (formal war der erste Parameter des ausgewählten Konstruktors keine rvalue-Referenz auf den (möglicherweise cv-qualifizierten) Typ des Ausdrucks)
(seit C++11)
(bis C++20)
  • dann wird die Überladungsauflösung wie üblich durchgeführt, wobei der Ausdruck als lvalue betrachtet wird (wodurch der Kopierkonstruktor ausgewählt werden könnte).
(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 Kopierelision

Wenn 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

return, co_return

[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