return statement
Terminates the current function and returns the specified value (if any) to the caller.
Syntax
attr (optional) return expression (optional) ;
|
(1) | ||||||||
attr (optional) return braced-init-list ;
|
(2) | (since C++11) | |||||||
attr (optional) co_return expression (optional) ;
|
(3) | (since C++20) | |||||||
attr (optional) co_return braced-init-list ;
|
(4) | (since C++20) | |||||||
| attr | - | (since C++11) sequence of any number of attributes |
| expression | - | expression, convertible to the function return type |
| braced-init-list | - | brace-enclosed initializer list |
Explanation
void, and disallowed in constructors and in destructors.The expression or braced-init-list(since C++11) (if any) is known as the operand of the return statement.
|
There is a sequence point between the copy-initialization of the result of the function call and the destruction of all temporaries at the end of expression. |
(until C++11) |
|
The copy-initialization of the result of the function call is sequenced-before the destruction of all temporaries at the end of expression, which, in turn, is sequenced-before the destruction of local variables of the block enclosing the |
(since C++11) |
|
If the return type of the function is a reference type and a |
(since C++26) |
If control reaches the end of
- a function with the return type (possibly cv-qualified)
void, - a constructor,
- a destructor, or
- a function
tryblock for a function with the return type (possibly cv-qualified)void
without encountering a return statement, return; is executed.
If control reaches the end of the main function, return 0; is executed.
Flowing off the end of a value-returning function, except the main function and specific coroutines(since C++20), without a return statement is undefined behavior.
In a function returning (possibly cv-qualified) void, the return statement with expression can be used, if the expression type is (possibly cv-qualified) void.
|
If the return type of a function is specified as a placeholder type, it will be deduced from the return value. If |
(since C++14) |
Notes
Returning by value may involve construction and copy/move of a temporary object, unless copy elision is used. Specifically, the conditions for copy/move are as follows:
Automatic move from local variables and parametersThe expression is move-eligible if it is a (possibly parenthesized) identifier expression that names a variable of automatic storage duration whose type is
|
(since C++11) |
|
(since C++20) |
|
and that variable is declared
of the innermost enclosing function or lambda expression. |
(since C++11) |
|
If the expression is move-eligible, overload resolution to select the constructor to use for initialization of the returned value or, for
|
(since C++11) (until C++23) |
|
(since C++11) (until C++20) |
|
(since C++11) (until C++23) |
|
If the expression is move-eligible, it is treated as an xvalue (thus overload resolution may select the move constructor). |
(since C++23) |
Guaranteed copy elisionIf expression is a prvalue, the result object is initialized directly by that expression. This does not involve a copy or move constructor when the types match (see copy elision). |
(since C++17) |
| Feature-test macro | Value | Std | Feature |
|---|---|---|---|
__cpp_implicit_move |
202207L |
(C++23) | Simpler implicit move |
Keywords
Example
#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
}
Output:
fa(1)
fb(4)
i = 2
fc(~).second = 7
fa(10)
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 1541 | C++98 | expression could not be omitted if the return type is cv-qualified void
|
it can be omitted |
| CWG 1579 | C++11 | return by converting move constructor was not allowed | converting move constructor lookup enabled |
| CWG 1885 | C++98 | sequencing of the destruction of automatic variables was not explicit | sequencing rules added |
See also
C documentation for
return statement |