2017-01-27 78 views
3

我有一个叫做Thing的对象,它的构造函数接受一个int值。构造函数调用的C++风格

此代码按预期工作:

Thing thing(5);

然而,意外我写了下面:

Thing thing = Thing(5); // note: no 'new'

,并得到了错误no matching constructor for initialization of 'Thing'。后面的代码的实际含义是什么?我知道这是什么意思,如果我扔了new在那里,但没有新的,这是什么意思?

+0

如何发生的?我没有在任何地方使用“显式” –

+0

@WhiZTiM'explicit'会阻止调用'Thing thing = 5'。 – rom1v

+3

显示“Thing”的整个类定义,或至少全部的构造函数。 –

回答

9

Thing thing(5);direct initliazation,thing由相应构造函数(即Thing::Thing(int))直接构建。

Thing thing = Thing(5);copy initialization,这与直接初始化不完全相同。但是对于这种情况,从C++ 17开始,它将直接调用Thing::Thing(int)来构造对象,然后它在这里与直接初始化具有相同的效果。

首先,如果T是一个类类型和初始值设定为prvalue表达式,其CV-非限定类型是相同的类T,初始化表达本身,而该临时从它物化,用于初始化目标对象:看到copy elision

C++ 17之前,第二情况下(即拷贝初始化)需要复制/移动的构造可访问和非显式;如果是这种情况,并且您使用的编译器不支持C++ 17,则会导致错误。

如果T是一个类类型和other类型的CV-不合格版本是T或从T派生的类,的T非显式的构造进行检查和最佳匹配是由过载分辨率来选择。然后调用构造函数来初始化该对象。

请注意,从C++ 17开始,代码会很好地编译。根据copy elision的规则,复制/移动构造函数不需要可访问,对于这种情况,explicit

在下列情况下,需要编译器省略 的复印通和类的构造函数MOVE-对象即使复制/移动 构造函数和析构函数具有可观察到的副作用:

  • 在初始化过程中,如果初始化表达式是一个prvalue,并且源类型的cv不合格版本与目标类的 类相同,则初始化表达式用于初始化目标对象 :

    T x = T(T(T())); // only one call to default constructor of T, to initialize x 
    
+0

IMO你说的是'事物= 5',而不是'事物=东西(5)'。在后者中,一旦定义了一个拷贝构造函数(但是这个拷贝构造函数不能是'explicit'),构造函数'Thing(int)''explicit'就可以了。 – rom1v

10
Thing thing = Thing(5); 

要求(非explicit)复印件(或移动)-constructor被定义为:

Thing(const Thing &); 

(即使它不是所谓优化的原因)。

+0

我明白了,所以公式就是在制作一件“事”,然后复制它(而不是毫无意义)。 –

+0

因为'Thing thing(5);'起作用,所以至少有一个构造函数'Thing(int)'('''explicit'''或'not'),所以你不能在没有看到类构造函数/成员 – P0W

+2

@ P0W的情况下得出结论。如果'Thing thing = Thing(5)'不起作用,IMO可以断定复制(/ move) - 构造器丢失。你能提供一个反例吗? – rom1v