假设我有一些带有删除拷贝构造函数的类:
struct NoCopy { NoCopy(int) {} NoCopy(const NoCopy &) = delete; };
我在另一个类中使用这个类:
struct Aggregate { NoCopy nc; };
但是当我尝试使用聚合初始化时
int main() { Aggregate a{3}; }
编译器输出以下错误:
error: use of deleted function ‘NoCopy::NoCopy(const NoCopy&)’
为什么聚合初始化需要类成员的副本构造函数?聚合初始化是否使用复制构造函数初始化所有成员?
您想要的正确语法是:
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
使用NoCopy(int)
构造函数在调用点处构造临时对象.然后,临时值通过值传递fun
,但由于NoCopy
不可复制,因此失败.
在该// right
版本中,您将为要构造的参数提供初始化列表.没有制作副本.