STL containers move semantics and return by value: how many times can copying be avoided?

I know that in C ++ 11, move semantics was implemented in STL containers to avoid temporary objects. And people say that now it is perfect for writing functions that return by value. But I have some confusion as to how many times copying can actually be avoided. See the following example:

vector<int> myVector() { vector<int> res; res.push_back(4); res.push_back(5); return res; } vector<int> v = myVector(); 

I understand that in C ++ 03, myVector returns a copy of res ( 4 , 5 , copied once), when evaluating the constructor vector<int> v = myVector(); vector<int> copy vector<int>(const vector<int> &) is called ( 4 , 5 copied twice). However, in C ++ 11 with move semantics, I want to know which copy of 4 and 5 can be avoided? both? Is it also called to optimize the value of the return value in order to reduce the copy time of 4 and 5 ?

+6
source share
1 answer

In C ++ 03, there are two copies and two movements in C ++ 11.

In both C ++ 03 and C ++ 11, copying / moving is subject to permission, and as such (for example, in the example) copy / moving will not occur.

 vector<int> myVector() { vector<int> res; res.push_back(4); res.push_back(5); return res;// <- Here we construct the return value with res } // here we construct v with the return value of myVector: vector<int> v = myVector(); 

The output from res to the return value of myVector somewhat fragile. In C ++ 11, move , which can occur if elision crashes is almost as free (as doing nothing) - 3 pointer instances and 3 pointers are cleared. In C ++ 03, a copy that can occur if a failure in elision can be expensive (memory allocation and O (n) copies).

Elision is the name of operational compilers that can run in certain circumstances when two values โ€‹โ€‹turn into one, even if this conversion causes a change in behavior (i.e. the as-if test fails).

When this happens, the lifetime is the unification of the two lifetimes.

In the above case, the local variable res and the return value myVector() can be overridden by the NRVO rule (using return value optimization). The return value of myVector can be discarded in v , since it is an expression of the form A a = b , where b is an expression that leads to an anonymous value (the name of such anonymous values โ€‹โ€‹changed from C + +03 to C ++ 11, so I wonโ€™t use it), in particular, the return value of myVector() .

This will cause the res v lifetime and the return value of myVector() be merged into one lifetime. In practice, what happens is that res is placed right where the return value of myVector() supposed to be (in accordance with the calling convention), as well as v , and the destruction of this combined value is skipped until v goes out of scope, as in the return and on v = myVector() .

Or, in other words, v is built directly in myVector .

+4
source

Source: https://habr.com/ru/post/979674/


All Articles