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 .
Cassio neri
source share