Reputation: 1028
Consider the following code. What happens when doStuff() is called but the return value is not used? Is SomeClass still created? Of course the creation itself can have important side effects, but so can copy-constructors and they are still omitted in RVO / copy-elision.
SomeClass doStuff(){
//...do stuff
return SomeClass( /**/);
}
SomeClass some_object = doStuff();
doStuff(); //What happens here?
(Edit: tested this with GCC -O3. The object is constructed and then destructed right away)
Upvotes: 19
Views: 2384
Reputation: 170065
I feel there's a misunderstanding when it comes to RVO and copy elision. It doesn't mean that a function's return value is not created. It's always created, that's not something an implementation can cop out of doing.
The only leeway, when it comes to eliding copies, despite side effects, is with cutting the middle man. When you initialize an object with the result of the call, then the standard allows plugging the target object in, for the function to initialize directly.
If you don't provide a target object (by using the result), then a temporary must be materialized, and destroyed, as part of the full expression that contains the function call.
So to play a bit with your example:
doStuff(); // An object is created and destroyed as part of temporary materialization
// Depending on the compilers analysis under the as-if rule, there may be
// further optimization which gets rid of it all. But there is an object there
// formally.
std::rand() && (doStuff(), std::rand());
// Depending on the result of std::rand(), this may or may not create an object.
// If the left sub-expression evaluates to a falsy value, no result object is materialized.
// Otherwise, one is materialized before the second call to std::rand() and
// destroyed after it.
Upvotes: 22
Reputation: 385114
A compiler may elide an unnecessary copy in certain cases, even if it has side effects, yes.
A compiler may not elide an object's entire existence, if it has side effects.
If it doesn't have side effects then no result is observable so whether the existence happened or not is effectively a non-question.
tl;dr: the standard lists very specific elision opportunities, and this is not one of them.
Upvotes: 6