C++风格的构造函数调用



我有一个名为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
    

最新更新