以下代码在使用或不使用用户定义的复制构造函数时表现不同 under GCC 8.0.1 :
#include <cassert>
struct S {
int i;
int *p;
S() : i(0), p(&i) {}
// S(const S &s) : i(s.i), p(&i) {} // #1
// S(const S &s) : i(s.i), p(s.p) {} // #2
// S(const S &s) = delete; // #3
};
S make_S() {return S{};}
int main()
{
S s = make_S();
assert(s.p == &s.i);
}
使用任一注释的用户定义复制构造函数(即使使用#2,执行简单浅复制的构造函数),断言都不会失败,这意味着 guaranteed copy elision按预期工作。
但是,如果没有任何用户定义的复制构造函数,断言将失败,这意味着 main
函数中的对象 s
不是默认构造的。为什么会这样?此处不保证执行复制省略?
最佳答案
引用自 C++17 工作草案§15.2 临时对象第 3 段(https://timsong-cpp.github.io/cppwp/class.temporary#3):
When an object of class type X is passed to or returned from a function, if each copy constructor, move constructor, and destructor of X is either trivial or deleted, and X has at least one non-deleted copy or move constructor, implementations are permitted to create a temporary object to hold the function parameter or result object. ... [ Note: This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. — end note]
在你的例子中,当我将复制和移动构造函数设置为默认值时:
S(const S &) = default;
S(S &&) = default;
GCC 和 Clang 的断言也失败了。请注意,隐式定义的构造函数是微不足道的。
关于c++ - 保证复制省略的行为是否取决于用户定义的复制构造函数的存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62408281/