Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy elision and temporary bound-by-ref object

Tags:

c++

c++11

The C++ draft states:

12.8p31 This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

(...)

  • when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

In other words:

X MakeX() {
   return X(); // Copy elided
}

X MakeX() {
   const X& x = X(); // Copy not elided
   return x;
}

What is the reason for such restriction for references?

Please do not focus on the validity of the following examples, as they are just to exemplify that I fail to see the difference (IMHO) between temporary and a reference.

On one hand by introduction of reference we allowed other peers to alias the same object, while the caller of MakeX() expects it to be safe and clean.

class Y {
public:
    Y(const X& x) : _xRef(x) {}
private:
    const X& _xRef;
};

X MakeX() {
    const X& x = X();
    Y y{x};
    StaticStuff::send(y);
    return x; // Oops, I promised to return a clean,
              // new object, but in fact it might be silently
              // changed by someone else. 
}

But what about such case (probably it's UB ;)):

class Y {
public:
    Y(X* x) : _xPtr(x) {}
private:
    X* _xRef;
};

X MakeX() {
    X x;
    Y y{&x}; // I'm referencing a local object but I know it will be
             // copy elided so present in the outer stack frame.
    StaticStuff::send(y);
    return x; // Copy elided?
}
like image 220
Red XIII Avatar asked Apr 08 '13 08:04

Red XIII


People also ask

What is copy elision in Javascript?

Copy elision is an optimization implemented by most compilers to prevent extra (potentially expensive) copies in certain situations. It makes returning by value or pass-by-value feasible in practice (restrictions apply).

What is copy move elision?

C++ Copy Elision Purpose of copy elision Copy elision (sometimes called return value optimization) is an optimization whereby, under certain specific circumstances, a compiler is permitted to avoid the copy or move even though the standard says that it must happen.

Is copy elision guaranteed?

In C++20, the only copy allowed in the example is the one at line 3 (actually, x is implicitly moved from). Copy elision (NRVO) is allowed there and is routinely performed by most compilers, but is still non-guaranteed, and the widget class cannot be non-copyable non-movable.

What is temporary materialization?

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.


1 Answers

You never know that a copy will be elided. Copy elision is never mandatory.

Therefore, either both cases are UB, or none. It depends on what StaticStuff:send does with the object you pass in. If it retains any poitner/reference to y._xRef or *y._xPtr, then dereferencing that pointer/reference after MakeX() has returned will indeed cause UB, as the original object x was one with automatic storage duration inside MakeX() and its lifetime has now ended.

It's possible that the result of this UB will be "everything works just fine" because copy ellision did take place and the pointer/reference refers to the instance in the "outer stack frame." However, this is pure coincidence and it's still UB.

like image 166
Angew is no longer proud of SO Avatar answered Oct 06 '22 20:10

Angew is no longer proud of SO