8 Statements [stmt.stmt]

8.7 Jump statements [stmt.jump]

8.7.4 The return statement [stmt.return]

A function returns control to its caller by the return statement.
The expr-or-braced-init-list of a return statement is called its operand.
A return statement with no operand shall be used only in a function whose return type is cv void, a constructor ([class.ctor]), or a destructor ([class.dtor]).
A return statement with an operand of type void shall be used only in a function that has a cv void return type.
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 from the operand.
[Note 1: 
A constructor or destructor does not have a return type.
— end note]
[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.
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]).
— end note]
The destructor for the result object is potentially invoked ([class.dtor], [except.ctor]).
[Example 1: class A { ~A() {} }; A f() { return A(); } // error: destructor of A is private (even though it is never invoked) — end example]
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.
Otherwise, flowing off the end of a function that is neither main ([basic.start.main]) nor a coroutine ([dcl.fct.def.coroutine]) results in undefined behavior.
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]) of the block enclosing the return statement.
In a function whose return type is a reference, other than an invented function for std​::​is_convertible ([meta.rel]), a return statement that binds the returned reference to a temporary expression ([class.temporary]) is ill-formed.
[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<decltype(r)&&>(r); } auto&& f3() { return id(42); // OK, but probably a bug } — end example]