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 将在复制之前丢弃 v 中的数据。没有 RVO 的代码是正确的,优化不应破坏行为。
这安全吗,还是我没有正确理解 RVO?
最佳答案
这是怎么回事:
在调用者这边,提供了一个可以保存结果的返回槽,这意味着调用者为类型为std::vector<int>
的变量提供了内存。 .它期望被调用的方法构造值,并负责在结果不再使用时调用析构函数并释放内存(如有必要,它可能只存在于堆栈中)。
如果没有 NRVO,被调用函数(可能存在于不同的翻译单元中!)会这样:
- 为
ret
提供内存插槽. - 构造局部变量
ret
在这个内存插槽中。 - 做事...
- 通过复制
ret
在提供的内存槽中复制构造返回值. - 调用
ret
的析构函数。
现在,有了 NRVO,可以在被调用函数的翻译单元中做出优化的决定。它将上面的转换为:
- 构造
ret
在方法返回槽的内存中。 - 做事...
不需要做任何其他事情,因为内存是自己的,析构函数是由调用者调用的,因为优化对调用者是透明的:)
当然,这不能消除对 v
的赋值。在你的例子中。如果您将结果存储在不同的变量中,例如
std::vector<int> w = f(v);
NRVO 将 build ret
直接进入w
的内存(因为这将作为返回槽传递给 f
)。
关于c++ - 这如何与返回值优化一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18662476/