vector<int> f(const vector<int>& v) { vector<int> ret(v.size()); fill(ret.begin(),ret.end(),123); copy(v.begin(),v.end(),ret.begin()); return ret; } int main() { vector<int> v(10); v = f(v); }
如果将返回值优化应用于f,则本地变量ret与main中的v共享相同的地址.但如果这是真的,填充ret将在复制之前废弃数据.没有RVO的代码是正确的,优化不应该破坏行为.
这样安全还是我不正确理解RVO?
解决方法
这是怎么回事:
在调用者方面,提供了一个可以保存结果的返回槽,这意味着调用者为std :: vector< int>类型的变量提供了内存.它期望被调用的方法构造值,并且当不再使用结果并释放内存时,它本身负责调用析构函数(如果需要,它可能只存在于堆栈中).
被调用的函数(可能存在于不同的翻译单元!),如果没有NRVO,那么:
>为ret提供内存插槽.
>在此内存插槽中构造一个局部变量ret.
>做点东西……
>复制 - 通过复制ret构造提供的内存插槽中的返回值.
>调用ret的析构函数.
现在,使用NRVO,可以在被调用函数的转换单元中完成对此进行优化的决定.它将上述内容转换为:
>在方法的返回槽的内存中构造ret.
>做点东西……
不需要做任何其他事情,因为内存是拥有的,并且调用者调用析构函数,因为优化对于调用者来说是透明的:)
当然,这不能消除示例中的赋值.如果将结果存储在不同的变量中,例如
std::vector<int> w = f(v);
NRVO将直接构造ret到w的内存中(因为它将作为返回槽传递给f).