All*_*nzi 6 c++ return-value move-semantics c++11
我知道在c ++ 11中,移动语义已经在STL容器中实现,以避免临时对象.人们说,现在编写按价值返回的函数是完美的.但我有一些关于地球上实际可以避免多少次复制的混淆.请参阅以下示例:
vector<int> myVector() {
vector<int> res;
res.push_back(4);
res.push_back(5);
return res;
}
vector<int> v = myVector();
Run Code Online (Sandbox Code Playgroud)
我的理解是,在C++ 03,myVector返回的副本res(4,5复制一次),当评估vector<int> v = myVector(); vector<int>的拷贝构造函数vector<int>(const vector<int> &)被调用(4,5复制两次).然而,在C++ 11移动语义,我想知道的哪个副本4和5被避免?都?是否还调用了返回值优化以减少一次复制4和5?
C++03中有两个副本,C++11中有两个移动。
在 C++03 和 C++11 中,复制/移动都会被省略,因此(在这样的例子中)不可能发生复制/移动。
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();
Run Code Online (Sandbox Code Playgroud)
省略掉res进入返回值myVector有点脆弱。在 C++11 中,move如果省略失败可能发生的情况几乎是免费的(就像什么都不做一样)——3 个指针副本,3 个指针清除。在 C++03 中,如果省略失败可能发生的复制可能很昂贵(内存分配和 O(n) 复制)。
Elision 是编译器在某些情况下可以执行的操作的名称,其中两个值转换为一个,即使该转换会导致行为发生变化(即,它无法通过 as-if 测试)。
发生这种情况时,组合值的生命周期是两个生命周期的并集。
在上述情况下,可以通过 NRVO 规则(命名返回值优化)省略局部变量res和返回值myVector()。的返回值myVector可以省略,v因为它是一种形式的语句,A a = b其中b是一个导致匿名值的表达式(此类匿名值的名称已从 C++03 更改为 C++11,因此我不会使用它),特别是myVector().
这会导致的生命周期res v和返回值myVector()合并为一个值生命周期。在实践中,发生的事情被res直接放置在返回值myVector()应该去的地方(根据调用约定),所以是v,并且销毁是跳过这个组合值直到v超出范围,就像构造中的return声明和上v = myVector()。
或者换句话说,v直接在myVector.