[stmt.return] # 8 Statements [[stmt]](./#stmt) ## 8.8 Jump statements [[stmt.jump]](stmt.jump#stmt.return) ### 8.8.4 The return statement [stmt.return] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1063) A function returns control to its caller by the return statement[.](#1.sentence-1) [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1066) The [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]") of a return statement is called its operand[.](#2.sentence-1) A return statement with no operand shall be used only in a function whose return type iscv void, a constructor ([[class.ctor]](class.ctor "11.4.5 Constructors")), or a destructor ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#2.sentence-2) A return statement with an operand of type void shall be used only in a function that has a cv void return type[.](#2.sentence-3) A return statement with any other operand shall be used only in a function that has a return type other than cv void;the return statement initializes the returned reference or prvalue result object of the (explicit or implicit) function call by [copy-initialization](dcl.init#def:copy-initialization "9.5 Initializers [dcl.init]") from the operand[.](#2.sentence-4) [*Note [1](#note-1)*: A constructor or destructor does not have a return type[.](#2.sentence-5) — *end note*] [*Note [2](#note-2)*: A return statement can involve an invocation of a constructor to perform a copy or move of the operand if it is not a prvalue or if its type differs from the return type of the function[.](#2.sentence-6) A copy operation associated with a return statement can be elided or converted to a move operation if an automatic storage duration variable is returned ([[class.copy.elision]](class.copy.elision "11.9.6 Copy/move elision"))[.](#2.sentence-7) — *end note*] [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1094) The destructor for the result object is potentially invoked ([[class.dtor]](class.dtor "11.4.7 Destructors"), [[except.ctor]](except.ctor "14.3 Stack unwinding"))[.](#3.sentence-1) [*Example [1](#example-1)*: class A {~A() {}}; A f() { return A(); } // error: destructor of A is private (even though it is never invoked) — *end example*] [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1106) Flowing off the end of a constructor, a destructor, or a non-coroutine function with a cv void return type is equivalent to a return with no operand[.](#4.sentence-1) Otherwise, flowing off the end of a function that is neither main ([[basic.start.main]](basic.start.main "6.10.3.1 main function")) nor a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")) results in undefined behavior[.](#4.sentence-2) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1116) The copy-initialization of the result of the call is sequenced before the destruction of temporaries at the end of the full-expression established by the operand of the return statement, which, in turn, is sequenced before the destruction of local variables ([[stmt.jump]](stmt.jump "8.8 Jump statements")) of the block enclosing the return statement[.](#5.sentence-1) [*Note [3](#note-3)*: These operations are sequenced before the destruction of local variables in each remaining enclosing block of the function ([[stmt.dcl]](stmt.dcl "8.10 Declaration statement")), which, in turn, is sequenced before the evaluation of postcondition assertions of the function ([[dcl.contract.func]](dcl.contract.func "9.4.1 General")), which, in turn, is sequenced before the destruction of function parameters ([[expr.call]](expr.call "7.6.1.3 Function call"))[.](#5.sentence-2) — *end note*] [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1133) In a function whose return type is a reference, other than an invented function for std​::​is_convertible ([[meta.rel]](meta.rel "21.3.8 Relationships between types")), a return statement that binds the returned reference to a temporary expression ([[class.temporary]](class.temporary "6.8.7 Temporary objects")) is ill-formed[.](#6.sentence-1) [*Example [2](#example-2)*: auto&& f1() {return 42; // ill-formed}const double& f2() {static int x = 42; return x; // ill-formed}auto&& id(auto&& r) {return static_cast(r);}auto&& f3() {return id(42); // OK, but probably a bug} — *end example*]