【问题标题】:C++ style of constructor callingC++ 风格的构造函数调用
【发布时间】:2017-06-12 23:55:26
【问题描述】:

我有一个名为 Thing 的对象,它的构造函数采用 int。

此代码按预期工作:

Thing thing(5);

但是,我偶然写了以下内容:

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

得到了错误no matching constructor for initialization of 'Thing'。后一个代码的实际含义是什么?我知道如果我把new 扔进去意味着什么,但没有新的,那是什么意思?

【问题讨论】:

  • 这是怎么发生的?我没有在任何地方使用explicit自己
  • @WhiZTiM explicit 会阻止调用 Thing thing = 5
  • 显示Thing的整个类定义,或者至少显示它的所有构造函数。

标签: c++ constructor initialization language-lawyer


【解决方案1】:
Thing thing = Thing(5);

需要定义一个(非explicit)复制(或移动)构造函数:

Thing(const Thing &);

(即使出于优化原因没有调用它)。

【讨论】:

  • 我明白了,所以这个公式正在制作一个 Thing 然后复制它(相当毫无意义)。
  • 如果没有看到类构造函数/成员,您无法得出结论
  • @P0W,因为Thing thing(5); 有效,所以至少有一个构造函数Thing(int)explicit 与否)。如果Thing thing = Thing(5) 不起作用,IMO 我们可以断定缺少复制(/移动)构造函数。你能举个反例吗?
  • @Виталик Бушаев 是的。
  • @P0W If Thing thing(5) 有效,Thing thing = Thing(5) 无效,then 非显式复制(或移动)构造函数不见了。您提供了一个示例,无需显式定义复制(或移动)构造函数即可使这两种声明工作。这不是不兼容的 ;-) 一个反例是一个工作的Thing thing(5),一个不工作的Thing thing = Thing(5),其解决方案是在不定义复制(或移动)构造函数的情况下使其工作。
【解决方案2】:

Thing thing(5);direct initliazationthing是由合适的构造函数(即Thing::Thing(int))直接构造的。

Thing thing = Thing(5);copy initialization,这与直接初始化并不完全相同。但是对于这种情况,从C++17开始,它也会直接调用Thing::Thing(int)来构造对象,那么和这里直接初始化的效果是一样的。

首先,如果T 是一个类类型,并且初始化程序是一个纯右值表达式,其 cv-unqualified 类型与T 是同一类,则初始化程序表达式本身,而不是由它实现的临时物化,用于初始化目标对象:见copy elision

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

如果T 是一个类类型并且other 的类型的cv 非限定版本是T 或派生自T 的类,则检查T 的非显式构造函数并最佳匹配是通过重载决议选择的。然后调用构造函数来初始化对象。

请注意,从 C++17 开始,代码可以正常编译。根据copy elision 的规则,复制/移动构造函数不需要可访问,explicit 在这种情况下。

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

  • 在初始化时,如果初始化表达式是纯右值并且源类型的 cv 非限定版本与 目标的类,初始化表达式用于 初始化目标对象:

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

【讨论】:

  • IMO 你说的是Thing thing = 5,而不是Thing thing = Thing(5)。在后者中,只要定义了复制构造函数,就可以将构造函数设为Thing(int)explicit(但此复制构造函数不能是explicit)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-19
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 2018-05-25
  • 1970-01-01
相关资源
最近更新 更多