Can a returned nested initializer lead to copying in C ++?

Example:

struct s { int a; }; s func() { return {42}; } int main() { s new_obj = func(); // line 6 (void) new_obj; return 0; } 

It works. Now, what happens if we assume that our compiler does not do RVO?

  • func returns the structure s , so {42} needs to be converted to s , then it is returned and finally copied to new_obj on line 6.
  • func returns a list of initializers, so a deep copy is not possible.

What does the language say? Can you give a proof?

Note. I know this doesn't seem useful in this example, but to return very large constants of size std::array s I don't want to rely on RVO.

+7
c ++ c ++ 11 return-value-optimization initializer-list
source share
1 answer

Consider the following example:

 #include <iostream> struct foo { foo(int) {} foo(const foo&) { std::cout << "copy\n"; } foo(foo&&) { std::cout << "move\n"; } }; foo f() { //return 42; return { 42 }; } int main() { foo obj = f(); (void) obj; } 

When compiling with gcc 4.8.1 with -fno-elide-constructors to prevent RVO output

 move 

If f uses the return statement without curly braces, then the output

 move move 

Without RVO, the following happens. f must create a temporary object of type foo to call its ret , which must be returned.

If used return { 42 }; , then ret directly initialized to 42 . Thus, the copy / move constructor has not been called so far.

If return 42; , then another temporary one, let tmp call it, initialize directly from 42 and tmp move to create ret . Therefore, one motion constructor has been called so far. (Note that tmp is an rvalue, and foo has a move constructor. If there was no move constructor, then the copy constructor will be called.)

Now ret is the value of r and is used to initialize obj . Therefore, the constuctor movement is called to move from ret to obj . (Again, in some cases, the copy constructor may be called instead.) Therefore, one of (for return { 42 }; ) or two (for return 42; ) occurs.

As I said in my commentary on the OP question, this post is very important: the make_XYZ construction assistant, which allows you to subtract RVO and type, even if XZY has an inaccuracy limit . A particularly excellent answer is R. Martinho Fernandes .

+5
source share

All Articles