Reputation: 757
Ignoring the copy/move elision from the compiler, I would like to know if the following code (assuming foo has a constructor accepting three ints) "syntactically" creates a temporary object and then copy/move initializes the function argument, or directly calls the constructor:
void acceptsFoo(foo a);
acceptsFoo({1, 2, 3});
And what about this case?
//ignoring RVO optimization
foo returnsFoo()
{
return {1, 2, 3};
}
I know that the code below, even without copy/move elision, is the same as calling the constructor so will not generate any temporary, but I couldn't find info about the code above.
foo = { 1, 2, 3 } //assuming the constructor is non-explicit
foo { 1, 2, 3 }
Upvotes: 1
Views: 2491
Reputation: 238301
void acceptsFoo(foo a); acceptsFoo({1, 2, 3});
No, there would not be a temporary in this case. The parameter is initialized directly from the argument expression.
//ignoring RVO optimization foo returnsFoo() { return {1, 2, 3}; }
Just like in the case of the argument, the return value is initialized directly from the return-statement.
However, the result of the function call expression would be a temporary object, yes. So, if you called the function like this: foo f = returnsFoo();
There would be two instances created. First the return value is initialized from the brace-initializer, then the variable bound object is copy initialized from the temporary (by move, if foo
is movable).
That is from the perspective of the abstract machine; the copy/move could be elided in practice (this is what RVO does).
However starting from C++17, in the statement foo f = returnsFoo();
, there would be no temporary and no copy/move to elide. On the other hand, in the statement returnsFoo();
, there would be a temporary created (which is destroyed immediately).
Upvotes: 2
Reputation: 473212
When a braced-init-list is used to initialize an object, it is used to initialize the object. Period.
Applying a braced-init-list to a function parameter means to initialize that parameter with the list of values, in accord with the rules of list initialization. When you return a braced-init-list, it is used to initialize the return value object with the list of values, in accord with the rules of list initialization.
There is no temporary object theoretically being copied into the parameter/return value.
Now (pre-C++17), if you had done acceptsFoo(foo{1, 2, 3});
or return foo{1, 2, 3}
, then that would provoke the creation of a temporary, which would then be used to initialize the parameter/return value.
Upvotes: 2