class 与不可复制成员的聚合初始化
Aggregate initialization of class with noncopyable member
假设我有一些 class 删除了复制构造函数:
struct NoCopy
{
NoCopy(int) {}
NoCopy(const NoCopy &) = delete;
};
我在另一个 class 中使用这个 class:
struct Aggregate
{
NoCopy nc;
};
但是当我尝试使用聚合初始化时
int main()
{
Aggregate a{3};
}
编译器输出以下错误:
error: use of deleted function ‘NoCopy::NoCopy(const NoCopy&)’
为什么聚合初始化需要class成员的拷贝构造函数?聚合初始化是否使用复制构造函数初始化所有成员?
您想要的正确语法是:
Aggregate a{{3}};
这为 NoCopy
成员提供了一个初始值设定项。如果没有额外的 {}
,编译器需要执行从 int
到 NoCopy
的转换(它很乐意通过非显式构造函数执行此操作),然后使用它来构造 nc
.这通常会作为移动构造发生,但通过删除复制构造函数,您也有效地删除了移动构造函数。
一种更简单的思考方式可能是想象 NoCopy
有一个值构造函数接受两个参数而不是一个参数:
struct NoCopy {
NoCopy(int, int);
};
现在如果你写
Aggregate a{1, 2};
表示 1
用于初始化 nc
而 2
用于初始化其他内容(编译时错误)。你必须添加额外的 {}
才能有意义
Aggregate a{{1, 2}};
第三种方法涉及查看函数调用:
struct NoCopy {
NoCopy(int) {}
NoCopy(const NoCopy &) = delete;
};
void fun(NoCopy) { }
int main() {
fun(1); // wrong
fun({1}); // right
}
在 // wrong
版本中,使用 NoCopy(int)
构造函数在调用点构造临时 NoCopy
对象。然后该临时值按值传递到 fun
,但由于 NoCopy
不可复制,因此失败。
在 // right
版本中,您为要构造的参数提供初始化列表。没有复制。
假设我有一些 class 删除了复制构造函数:
struct NoCopy
{
NoCopy(int) {}
NoCopy(const NoCopy &) = delete;
};
我在另一个 class 中使用这个 class:
struct Aggregate
{
NoCopy nc;
};
但是当我尝试使用聚合初始化时
int main()
{
Aggregate a{3};
}
编译器输出以下错误:
error: use of deleted function ‘NoCopy::NoCopy(const NoCopy&)’
为什么聚合初始化需要class成员的拷贝构造函数?聚合初始化是否使用复制构造函数初始化所有成员?
您想要的正确语法是:
Aggregate a{{3}};
这为 NoCopy
成员提供了一个初始值设定项。如果没有额外的 {}
,编译器需要执行从 int
到 NoCopy
的转换(它很乐意通过非显式构造函数执行此操作),然后使用它来构造 nc
.这通常会作为移动构造发生,但通过删除复制构造函数,您也有效地删除了移动构造函数。
一种更简单的思考方式可能是想象 NoCopy
有一个值构造函数接受两个参数而不是一个参数:
struct NoCopy {
NoCopy(int, int);
};
现在如果你写
Aggregate a{1, 2};
表示 1
用于初始化 nc
而 2
用于初始化其他内容(编译时错误)。你必须添加额外的 {}
才能有意义
Aggregate a{{1, 2}};
第三种方法涉及查看函数调用:
struct NoCopy {
NoCopy(int) {}
NoCopy(const NoCopy &) = delete;
};
void fun(NoCopy) { }
int main() {
fun(1); // wrong
fun({1}); // right
}
在 // wrong
版本中,使用 NoCopy(int)
构造函数在调用点构造临时 NoCopy
对象。然后该临时值按值传递到 fun
,但由于 NoCopy
不可复制,因此失败。
在 // right
版本中,您为要构造的参数提供初始化列表。没有复制。