我有一个名为Thing
的对象,它的构造函数采用int。
此代码按预期工作:
Thing thing(5);
然而,我无意中写下了以下内容:
Thing thing = Thing(5); // note: no 'new'
并得到了误差no matching constructor for initialization of 'Thing'
。后一个代码的实际含义是什么?我知道如果我把new
扔进去意味着什么,但没有新的,这意味着什么?
Thing thing = Thing(5);
需要定义一个(非explicit
)复制(或移动)构造函数:
Thing(const Thing &);
(即使出于优化原因没有调用它)。
Thing thing(5);
是直接初始化,thing
是由同位构造函数(即Thing::Thing(int)
)直接构造的。
Thing thing = Thing(5);
是复制初始化,与直接初始化不完全相同。但对于这种情况,由于C++17,它也会直接调用Thing::Thing(int)
来构造对象,那么它在这里与直接初始化具有相同的效果。
首先,如果
T
是一个类类型,并且初始化器是一个prvalue表达式,其cv不合格类型与T
是同一类,则初始化器表达式本身,而不是从中临时物化的,用于初始化目标对象:请参阅复制省略
在C++17之前,第二种情况(即复制初始化)要求复制/移动构造函数是可访问的且非显式的;如果是这种情况,并且您使用的编译器不支持C++17,则会导致错误。
如果
T
是一个类类型,并且other
的类型的cv不合格版本是T
或从T
派生的类,则检查T
的非显式构造函数,并通过重载解析选择最佳匹配。然后调用构造函数来初始化对象。
请注意,从C++17开始,代码将编译良好。根据复制省略规则,复制/移动构造函数不需要是可访问的,在这种情况下为explicit
。
在以下情况下,编译器需要省略类对象的复制和移动构造函数,即使是复制/移动构造函数和析构函数有明显的副作用:
在初始化中,如果初始值设定项表达式是prvalue,并且源类型的cv不合格版本与类,初始化器表达式用于初始化目标对象:
T x = T(T(T())); // only one call to default constructor of T, to initialize x