4

让我们考虑下一个示例:

struct big_type {};

// Return by copy
auto factory() { return big_type{}; }

void any_scope_or_function() {
    big_type&& lifetime_extended = factory();
}

在假设 RVO 被禁止或根本不存在并且以任何方式存在的情况下,是否会或可以big_type()复制?还是将引用直接绑定到return语句中构造的临时变量?

我想确保在结束big_type时只调用一次析构函数any_scope_or_function

我使用 C++14,以防标准版本之间的某些行为发生了变化。

4

2 回答 2

8

假设没有 RVO/复制 elison 然后在

auto factory() { return big_type{}; }

big_type{}将创建一个临时的big_type. 然后该对象将用于复制初始化函数返回的对象。这意味着您在函数中创建的对象将被构造和破坏。

big_type&& lifetime_extended = factory();

右值引用将延长函数返回的生命周期,因此我们将总共看到一个默认构造函数调用、一个复制/移动构造函数调用和两个析构函数调用。

现在,如果我们改变

auto factory() { return big_type{}; }

big_type factory() { return {}; }

然后我们不再在工厂中创建对象。返回对象直接初始化,{}总共给我们一个默认的构造函数调用和一个析构函数调用

于 2017-06-27T19:26:28.437 回答
3

还是将引用直接绑定到 return 语句中构造的临时变量?

不,不会的。这正是 (N)RVO 的意义所在,您明确不希望这样。

但是,将尝试使用 your 的移动构造函数big_type,这在技术上不是副本。它确实违反了:“析构函数在结束big_type时只被调用一次any_scope_or_function”,因为它会被调用两次。

GCC/Clang 有一个不错的编译器开关:-fno-elide-constructors禁用 (N)RVO,可用于将来参考。现在,是一个打开了该选项的测试,显示了双重析构函数调用。

于 2017-06-27T19:26:29.270 回答