Given
struct Range{
Range(double from, double to) : from(from), to(to) {}
double from;
double to;
// if it matters to the compiler, we can add more fields here to make copying expensive
};
struct Box{
Box(Range x, Range y) : x(x), y(y) {}
Range x;
Range y;
};
someone said that in Box box(Range(0.0,1.0),Range(0.0,2.0))
, the compiler can avoid copying Range
objects altogether by constructing them inside box
to begin with.
Does any compiler actually do this?
My own attempts haven't succeeded.
Compilers often perform Named Return Value Optimization (NRVO) in such cases, but it is not guaranteed.
Guaranteed copy elision redefines a number of C++ concepts, such that certain circumstances where copies/moves could be elided don't actually provoke a copy/move at all. The compiler isn't eliding a copy; the standard says that no such copying could ever happen. Consider this function: T Func() {return T();}
Temporary materializationA prvalue of any complete type T can be converted to an xvalue of the same type T . This conversion initializes a temporary object of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object.
The compiler can - and normally does - elide the copies from the temporary to the argument. The compiler cannot elide the copy from the argument to members. While it may technically possible to elide these copies in some cases, the relevant permission isn't given. The section of the standard is 12.8 [class.copy] paragraph 31 which spells out 4 situations where a copy can be elided (the exact rules are a bit non-trivial):
throw
expression.Passing a named argument as parameter to the construction of a member variable is, clearly, none of these situations.
The essential background of the rules for copy elision is that in some contexts the declaration of functions suffice to determine when an object will be used. If it is clear upon construction time where the object can be constructed, it can be elided. The caller of a constructor cannot determine based only on the declaration of the constructor where the object will be used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With