让我们考虑下一个样本:
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,以防某些行为在标准版本之间发生变化。
答案 0 :(得分:8)
假设在
中没有RVO /拷贝elisonauto factory() { return big_type{}; }
big_type{}
将创建一个临时big_type
。然后,此对象将用于复制初始化函数返回的对象。这意味着您在函数中创建的对象将被构造和销毁。
使用
big_type&& lifetime_extended = factory();
rvalue引用将延长函数返回的生命周期,因此我们将总共看到一个默认构造函数调用,一个复制/移动构造函数调用和两个析构函数调用。
现在,如果我们改变
auto factory() { return big_type{}; }
到
big_type factory() { return {}; }
然后我们不再在工厂中创建对象了。使用{}
直接初始化return对象,总共给出了一个默认的构造函数调用和一个析构函数调用
答案 1 :(得分:3)
或者引用会直接绑定到临时构造的 在退货声明中?
不,它不会。这正是(N)RVO所关注的/你明确地不想要那个。
但是,将尝试使用big_type
的移动构造函数,这在技术上不是副本。它确实违反了:“{em> big_type
析构函数只在any_scope_or_function
结束”时被调用一次,但因为它将被调用两次。
GCC / Clang有一个很好的编译器开关:-fno-elide-constructors
,它禁用(N)RVO,可用于将来的参考。目前,here是一个打开该选项的测试,显示双析构函数调用。