无论有或没有用户定义的复制构造函数,以下代码的行为都不同在 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,即执行简单浅复制的构造函数),断言都不会失败,这意味着保证复制省略按预期工作。
但是,如果没有任何用户定义的复制构造函数,断言就会失败,这意味着对象s
in main
函数不是默认构造的。为什么会出现这种情况?这里不保证复制省略执行吗?
引用自 C++17 工作草案 §15.2 临时对象第 3 段(https://timsong-cpp.github.io/cppwp/class.temporary#3):
当类类型 X 的对象传递给或从函数返回,如果 X 的每个复制构造函数、移动构造函数和析构函数都是平凡的或已删除的,并且 X 至少有一个未删除的复制或移动构造函数,允许实现创建一个临时对象来保存函数参数或结果对象。 ... [Note:授予此自由度是为了允许将类类型的对象传递到寄存器中的函数或从寄存器中的函数返回。 —end note]
在您的情况下,当我将复制和移动构造函数设置为默认值时:
S(const S &) = default;
S(S &&) = default;
GCC 和 Clang 的断言也失败。请注意,隐式定义的构造函数很简单。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)