C++ 标准:return 通过复制来初始化没有 RVO 的引用:有没有复制?
C++ standard: return by copy to initialize a reference without RVO: is there any copy?
让我们考虑下一个示例:
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,以防某些行为在标准版本之间发生变化。
假设没有 RVO/copy elison 那么
auto factory() { return big_type{}; }
big_type{}
将创建一个临时 big_type
。然后,该对象将用于复制初始化 函数return 对象。这意味着您在函数中创建的对象将被构造和析构。
有
big_type&& lifetime_extended = factory();
右值引用将延长函数的生命周期 return 因此我们将总共看到一个默认构造函数调用、一个 copy/move 构造函数调用和两个析构函数调用。
现在,如果我们改变
auto factory() { return big_type{}; }
到
big_type factory() { return {}; }
然后我们不再在工厂中创建对象。 return 对象直接用 {}
初始化,总共给我们一个默认的构造函数调用和一个析构函数调用
Or will the reference be directly bound to the temporary constructed
within the return statement?
不,不会。这正是 (N)RVO about/for 而你明确不想要的。
但是,将尝试使用您的 big_type
的移动构造函数,这在技术上不是副本。它确实违反了:“big_type
析构函数仅在 any_scope_or_function
结束时被调用一次 ” 尽管它会被调用两次。
GCC/Clang 有一个很好的编译器开关:-fno-elide-constructors
禁用 (N)RVO,可用于将来参考。目前,here 是一个启用了该选项的测试,显示了双重析构函数调用。
让我们考虑下一个示例:
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,以防某些行为在标准版本之间发生变化。
假设没有 RVO/copy elison 那么
auto factory() { return big_type{}; }
big_type{}
将创建一个临时 big_type
。然后,该对象将用于复制初始化 函数return 对象。这意味着您在函数中创建的对象将被构造和析构。
有
big_type&& lifetime_extended = factory();
右值引用将延长函数的生命周期 return 因此我们将总共看到一个默认构造函数调用、一个 copy/move 构造函数调用和两个析构函数调用。
现在,如果我们改变
auto factory() { return big_type{}; }
到
big_type factory() { return {}; }
然后我们不再在工厂中创建对象。 return 对象直接用 {}
初始化,总共给我们一个默认的构造函数调用和一个析构函数调用
Or will the reference be directly bound to the temporary constructed within the return statement?
不,不会。这正是 (N)RVO about/for 而你明确不想要的。
但是,将尝试使用您的 big_type
的移动构造函数,这在技术上不是副本。它确实违反了:“big_type
析构函数仅在 any_scope_or_function
结束时被调用一次 ” 尽管它会被调用两次。
GCC/Clang 有一个很好的编译器开关:-fno-elide-constructors
禁用 (N)RVO,可用于将来参考。目前,here 是一个启用了该选项的测试,显示了双重析构函数调用。