Issue
Say I have the following code.
class A
{
public:
float x, y, z;
A(float x, float y, float z) : x(x), y(y), z(z) {}
};
float average(A a)
{
return (a.x + a.y + a.z) / 3;
}
Are there any practical differences between calling the function in these two ways?
// a)
average(A(1, 2, 3))
// b)
average({1, 2, 3})
Solution
It depends on the C++ version you are using.
Copied (and sligthly modified) from copy elision @ cpprefrence (so, not an exact quote):
In C++17 core language specification of
prvalues
and temporaries is fundamentally different from that of the earlier C++ revisions: there is no longer a temporary to copy/move from.
This means that the temporary A
you visually show in average(A(1, 2, 3))
is not allowed to be copied or moved since C++17. In fact, there is no temporary. Before C++17, most compilers utilized copy (and move) elision (that has been allowed earlier too, but it wasn't mandatory) to the same effect - but you could not portably rely on it.
In C++17, this form of copy elision was made mandatory and is since called Return Value Optimization, or RVO for short. You will also read about Named RVO (or NRVO), which is similar, but does not follow the same rules. It's a bit more complicated and outside the scope of this answer.
Before C++17, average(A(1, 2, 3))
could actually mean that a temporary instance of A
is created and that the move or copy constructor of the A
in the function would have to move (or for a non-movable, copy) the resources from that temporary - which is usually cheap, but doesn't have to be - and it could come with side effects.
Some types are neither copyable nor movable. In such cases, the call would not be valid before C++17. In C++17, delete
d move and copy constructors does not matter in this case since there is no instance to move or copy from - and the call is therefore undoubtedly valid.
When using the brace enclosed initializer list, as you do in this example, not even C++11 is allowed to create (and move) a temporary instance of A
. The values are passed directly to the constructor in A(float x, float y, float z)
.
Other that that, I can't spot a difference in your example.
Answered By - Ted Lyngmo Answer Checked By - David Goodson (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.