See the below example of returning an optional of UserName
- a movable/copyable class.
std::optional<UserName> CreateUser() { UserName u; return {u}; // this one will cause a copy of UserName return u; // this one moves UserName } int main() { auto d = CreateUser(); }
Why does return {u}
cause a copy and return u
a move?
Here's the related coliru sample: http://coliru.stacked-crooked.com/a/6bf853750b38d110
Another case (thanks to the comment from @Slava):
std::unique_ptr<int> foo() { std::unique_ptr<int> p; return {p}; // uses copy of unique_ptr and so it breaks... }
Returning an object invokes the copy constructor while returning a reference doesn't. So, the version #2 does less work and is more efficient. The reference should be to an object that exists when the calling function is execution.
The class template std::optional manages an optional contained value, i.e. a value that may or may not be present. A common use case for optional is the return value of a function that may fail.
What's more, std::optional doesn't need to allocate any memory on the free store. std::optional is a part of C++ vocabulary types along with std::any , std::variant and std::string_view .
Because returning a name of an object with automatic storage duration is treated as returning an rvalue of the object. Note this works only if the expression in the return statement is a (possibly parenthesized, not including braces) name, like return u;
or return (u);
, so return {u};
works as usual, i.e. the copy constructor is invoked.
Related part in the standard [class.copy.elision]/3:
In the following copy-initialization contexts, a move operation might be used instead of a copy operation:
- If the expression in a return statement ([stmt.return]) is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or
- ...
overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With