[英]Default member variables in defaulted copy/move constructors
在默认复制/移动构造期间,具有默认值的成员变量究竟发生了什么? 如此:
struct A {bool a = true;};
A x;
x.a = false;
A y = x;
我可以想象几种不同的工作方式,等效地写为
struct A {bool a;}; //no default
//option 1
A::A(const A& other) noexcept : a(other.a) {}
//option 2
A::A(const A& other) noexcept : a(true) {a = other.a;}
//option 3
A::A(const A& other) noexcept {a = other.a;}
//option 4 (hopefully not)
A::A(const A& other) noexcept : a(true) {}
除了明显的例外,使用这些会使 A 不是TriviallyCopyable
构造函数必须并且将始终初始化所有 class 数据成员。
默认初始化器将用于未显式初始化该数据成员的构造函数。 默认复制构造函数将使用来自复制的 object 的相应数据成员的副本初始化每个数据成员,因此不会使用默认初始化程序。
这会导致在复制构造函数中使用默认初始值设定项(如果它是用户提供的并且缺少该成员初始值设定项)的情况(感谢 NathanOliver 指出这一点)。
例如:
A(whatever param) {} // default initializer used
A(whatever param) : a{true} {} // default initializer NOT used
A(const A&) = default; // default initializer NOT used
A(const A&) : a{other.a} {} // default initializer NOT used
A(const A&) {} // default initializer used
快速测试,我们将看到A
的默认Loud
成员是如何在A
的默认复制构造函数期间初始化和复制的:
#include <iostream>
struct Loud {
Loud(bool a) : b(a) {
std::cout << "ctr with value " << b <<std::endl;
}
Loud(const Loud& other) noexcept : b(other.b) {
std::cout << "cpyctr with value " << b << std::endl;
}
Loud& operator=(const Loud& other) noexcept {
b = other.b;
std::cout << "cpyasn with value " << b << std::endl;
return *this;
}
bool b;
};
struct A {Loud a = true;};
int main(int argc, char** argv) {
A x; //1
x.a = false; //2
A y = x; //3
return 0;
}
在-O0
,产生:
ctr with value 1 //1 (constructing x)
ctr with value 0 //2 (implicit conversion from `false`)
cpyasn with value 0 //2 (assigning to x)
cpyctr with value 0 //3 (constructing y)
这意味着A
的默认构造函数的行为与
//option 1
A::A(const A& other) noexcept : a(other.a) {}
这支持另一个答案(具有默认值的成员)没有任何可见的效果
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.