Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does returning a std::optional sometimes move and sometimes copy?

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... } 
like image 920
fen Avatar asked Jul 18 '18 13:07

fen


People also ask

Does returning an object copy it C++?

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.

What is the use of std :: optional?

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.

Does STD optional allocate?

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 .


1 Answers

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.

like image 103
xskxzr Avatar answered Oct 08 '22 15:10

xskxzr