How does guaranteed copy work?

At the 2016 Oulu ISO C ++ Standards Meeting, a proposal called Guaranteed text copying through simplified value categories was voted on by the C ++ 17 standardization committee.

How exactly does guaranteed copy work? Does it cover some cases where permission to copy has already been allowed, or code changes necessary to guarantee copying?

+65
c ++ c ++ 1z copy-elision c ++ 17
Jun 26 '16 at 21:23
source share
1 answer

Copying permissions was allowed in a number of cases. However, even if it was allowed, the code should still work as if the copy were not deleted. Namely, an accessible instance and / or movement mechanism must exist.

A guaranteed copy of elision redefines a number of C ++ concepts, so certain circumstances under which copies / movements can be deleted do not actually provoke copying / moving at all. The compiler does not copy the copy; the standard says that such a copy could not have happened.

Consider this function:

T Func() {return T();} 

In accordance with the not guaranteed rules for eliminating a copy, this will create a temporary one and then move from this temporary to the return value of the function. This move operation can be undone, but T should still have a move constructor available, even if it is never used.

Similarly:

 T t = Func(); 

This is the initialization of copying T This will copy the initialize T with the return value of Func . However, T still needs to have a move constructor, although it will not be called.

Guaranteed elision copy overrides the value of the prvalue expression . Pre-C ++ 17, prvalues ​​are temporary objects. In C ++ 17, the prvalue expression is just something that can materialize temporary, but it is not yet temporary.

If you use the prvalue value to initialize an object of type prvalue, then the temporary will not be implemented. When you do return T(); , this initializes the return value of the function through prvalue. Since this function returns T , a temporary creation is not created; prvalue initialization simply directly initializes the return value.

The fact is, since the return value is a prvalue, it is not an object. It is just an initializer for an object, just like T() .

When you execute T t = Func(); , prvalue of the return value directly initializes the T object; no "create temporary and copy / move". Since Func() return value is equivalent to T() , T directly initialized to T() , just as if you did T t = T() .

If prvalue is used in any other way, prvalue will materialize the temporary object that will be used in this expression (or discarded if there is no expression). So if you did const T &rt = Func(); , then prvalue will materialize the temporary (using T() as an initializer), the link to which will be stored in rt , as well as the usual material of a temporary extension of life.

One guaranteed elite allows you to return objects that are motionless. For example, lock_guard cannot be copied or moved, so you cannot have a function that returns it by value. But with guaranteed copy resolution you can.

Guaranteed elision also works with direct initialization:

 new T(FactoryFunction()); 

If FactoryFunction returns T by value, this expression will not copy the return value to the allocated memory. Instead, it will allocate memory and use the allocated memory as return value memory for direct function invocation.

So, factory functions that return by value can directly initialize the allocated heap of memory without even knowing about it. As long as these functions follow the rules of guaranteed copy internally, of course. They must return a value of type T

Of course, this also works:

 new auto(FactoryFunction()); 

If you do not like to write type names.




It is important to recognize that the above warranties only work for prvalues. That is, you do not receive any guarantee when returning a named variable:

 T Func() { T t = ...; ... return t; } 

In this case, T should still have a copy / move constructor available. Yes, the compiler can choose copy / move optimization. But the compiler should still check for the availability of the copy / move constructor available.

Thus, nothing will change for named return value optimization (NRVO).

+94
Jun 26 '16 at 21:40
source share



All Articles