Copy elision and temporary bound-by-ref object

The C ++ project states:

12.8p31 This permission of copy / move operations, called copying, is allowed in the following cases (which can be combined to eliminate multiple copies):

(...)

  • when a temporary class object that was not attached to a link (12.2) is copied / moved to a class object with the same cv-unqualified type, the copy / move operation can be omitted from building the temporary object directly to the target of the missed 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 this limitation for links ?

Please do not focus on the reliability of the following examples, as they simply illustrate that I do not see the difference (IMHO) between the temporary and the link.

On the one hand, by introducing the link, we allowed the other peers to use the same object, and the calling MakeX() object expected 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 this case (maybe 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? } 
+6
source share
1 answer

You never know that a copy will be deleted. Copying elision is never required.

Therefore, both cases are UB, or none. It depends on what StaticStuff:send does with the object you are passing in. If it saves any poitner / reference to y._xRef or *y._xPtr , then dereferencing that the pointer / link after MakeX() returned will actually call UB, since the original object x was the one with automatic storage time inside MakeX() , and its service life has ended.

It is possible that the result of this UB will be “everything works fine”, because copying occurs, and the pointer / link refers to the instance in the “external stack”. However, this is pure coincidence, and it is still UB.

+3
source

All Articles