The difference between the two is really quite subtle. C++11 introduced the feature list initialization (also sometimes called brace initialization):
Before C++11, when you want to default-construct and object o
of type Obj
and construct a Position p
from o
, you had to write
Obj o; // default construct o
Obj::Position p(o); // construct p using Position(Obj const&)
A common error for beginners (especially with a Java background) was to try to write this:
Obj o(); // mistake: declares a function o returning an Obj
Obj::Position p(o); // error: no constructor takes a function
The first line declares a function, and the second one tries to create a Position
using a constructor that takes a function pointer as its argument. In order to have a uniform initializer syntax, C++11 introduced list initialization:
Obj oo{}; // new in C++11: default construct o of type Obj
Obj::Position p1(oo); // possible before (and after) C++11
Obj::Position p2{oo}; // new in C++11: construct p2 using Position(Obj const&)
This new syntax also works in return
-statements, and this leads to the answer of your question: the difference between return {*this};
and return *this;
is that the former initializes the return value directly from *this
, whereas the latter first converts *this
to a temporary Position
object and then initializes the return value indirectly from this temporary, which fails because both the copy- and move-constructor have been explicitly deleted.
As the previous posters have noted, most compilers elide these temporary objects because they aren't really useful for anything; but this is only possible if they could be used in theory because either a copy or a move constructor is available. Because this leads to a lot of confusion (why do I need braces around my return statement? is the compiler going to elide the copy or not?), C++17 does away with these unnecessary temporaries, and initializes the return value directly in both cases (return {*this};
and return *this
).
You can try this using a compiler that supports C++17. In clang 4.0 or gcc 7.1, you can pass --std=c++1z
, and your code should compile fine with and without braces.