保证复制省略的行为是否取决于用户定义的复制构造函数的存在?
Does the behavior of guaranteed copy elision depend on existence of user-defined copy constructor?
以下代码在使用或不使用用户定义的复制构造函数时表现不同 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,执行简单浅拷贝的构造函数),断言都不会失败,这意味着 按预期工作。
但是,没有任何用户定义的复制构造函数,断言失败,这意味着 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 的断言也失败了。请注意,implicitly-defined 构造函数是微不足道的。
以下代码在使用或不使用用户定义的复制构造函数时表现不同 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,执行简单浅拷贝的构造函数),断言都不会失败,这意味着
但是,没有任何用户定义的复制构造函数,断言失败,这意味着 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 的断言也失败了。请注意,implicitly-defined 构造函数是微不足道的。