gpt4 book ai didi

c++ - 为什么在返回参数时不允许 RVO?

转载 作者:IT老高 更新时间:2023-10-28 21:47:48 27 4
gpt4 key购买 nike

在 [C++11: 12.8/31] 中有说明:

This elision of copy/move operations, called copy elision, is permitted [...] :

— in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

这意味着

#include <iostream>

using namespace std;

struct X
{
X() { }
X(const X& other) { cout << "X(const X& other)" << endl; }
};

X no_rvo(X x) {
cout << "no_rvo" << endl;
return x;
}

int main() {
X x_orig;
X x_copy = no_rvo(x_orig);

return 0;
}

将打印

X(const X& other)
no_rvo
X(const X& other)

为什么需要第二个拷贝构造函数?编译器不能简单地延长 x 的生命周期吗?

最佳答案

想象 no_rvo 定义在与 main 不同的文件中,这样在编译 main 时编译器只会看到声明

X no_rvo(X x);

并且不知道返回的 X 类型的对象是否与参数有 any 关系。据当时所知,no_rvo 的实现也可以是

X no_rvo(X x) { X other; return other; }

所以当它例如编译行

X const& x = no_rvo(X());

在最大限度优化时会执行以下操作。

  • 生成临时 X 作为参数传递给 no_rvo
  • 调用no_rvo,并将其返回值绑定(bind)到x
  • destruct 它传递给 no_rvo 的临时对象。

现在,如果 no_rvo 的返回值与传递给它的对象是同一个对象,那么临时对象的销毁将意味着返回的对象的销毁。但这将是错误的,因为返回的对象绑定(bind)到一个引用,因此将其生命周期延长到该语句之外。然而,简单地不破坏参数也不是解决方案,因为如果 no_rvo 的定义是我上面显示的替代实现,那将是错误的。因此,如果允许函数重用参数作为返回值,则可能会出现编译器无法确定正确行为的情况。

请注意,对于常见的实现,编译器无论如何都无法优化它,因此正式允许它并不是一个很大的损失。另请注意,如果编译器能够证明这不会导致可观察行为发生变化(所谓的 as-if 规则),那么编译器允许优化拷贝。

关于c++ - 为什么在返回参数时不允许 RVO?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9444485/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com