C ++-为什么在没有明显的构造函数匹配时为什么会编译此代码?

大卫

请考虑以下代码:

class Foo {
 public:
  explicit Foo(double) {}
};

Foo * test();
Foo * test() {
  return new Foo(Foo(1.0));   // (1)
}

我的问题与第(1)行有关。这与我花了一些时间进行跟踪的错误非常相似。我没有注意到由于复制/粘贴错误而两次指定了该类型。正确的行显然是:

  return new Foo(1.0);

有趣的是,此更改似乎也可以无警告地进行编译:

  return new Foo(Foo(Foo(Foo(1.0))));

为什么这些示例即使在带有-Wall -Weverything标志的情况下也不会发出带有警告的警告为什么Foo::Foo(double)接受Foo的实例作为有效double参数?这是运算符的某些特殊行为吗?

我的原始代码是在较大的上下文中使用的,并且已使用两个基于LLVM-3的编译器进行了测试。两者编译时都没有警告或错误。有了它,代码实际上按我的预期运行了,实际上我有一段时间没有意识到有错误了。另一个实例的Foo实例的行为非常奇怪-我无法真正正确地描述它-好像返回的指针的更高版本“神奇地”变成了与原始指针不同的值,从而导致两个协作对象之间的状态不匹配本来应该持有指向共享Foo的等效指针的对象,但是由于某些原因,在分配后它们持有不同的值。直到我了解这里发生的事情,这似乎才是真正的怪异!

有趣的是,以下两个编译器均可进行编译:

class Foo { public: explicit Foo(double) {} };
class Bar { public: explicit Bar(double) {} };

Foo * testFoo() { return new Foo(Foo(1.0)); }
Bar * testBar() { return new Bar(Bar(1.0)); }

但是以下版本没有:

Foo * testFooBar() { return new Foo(Bar(1.0)); }
小狗

编译器会自动生成一个副本构造函数,Foo(const Foo&)并可能还会根据确切的版本/设置移动构造函数Foo(Foo&&)这与new运算符或任何指针魔术无关。您的代码只需调用编译器为您定义的完全正常的复制/移动构造函数。就这样。此行为是标准规定的。不可复制的类(至少在标准的原始版本中)几乎毫无用处。

如果您不希望自动生成副本构造函数,通常的技术是将它们定义为已删除或私有。

还要注意,在某些情况下,编译器有权从程序中实际删除整个对象,尽管通常情况下不应这样做。如果使用Foo构造函数中的Foo指针设置hijinks,则必须在所有构造函数和析构函数中严格处理它们,这意味着必须编写自己的复制/移动构造函数,析构函数和赋值运算符,否则您会来编译器隐藏对象时的裁剪器。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么在没有类型不匹配错误的情况下编译此代码(C ++ 11)?

为什么此std :: string C ++代码没有给出编译时错误?

为什么C标准允许此代码编译时没有错误?

为什么此代码在C ++ 17中编译时没有错误?

C ++:没有匹配的调用函数:为什么需要一个空的构造函数?

为什么此代码可以编译直至C ++ 17且没有错误?

为什么此代码在在线 C++ 编译器上没有输出?

“ +”号的行为是什么,为什么c ++会编译它?

为什么在C ++ 4.8.2中无法编译此C ++代码

为什么在char c =''不编译时,新的String(“”)会编译?

当类具有引用成员时,为什么C ++编译器不删除副本构造函数?

为什么递归构造函数调用会使无效的C#代码编译?

为什么此C ++代码段编译(非void函数不返回值)

VS2013 C99-为什么会编译?

为什么此C ++代码没有返回数组中每个字符的地址?

为什么我的 C++ 代码在我尝试编译时不断返回“未定义的引用”到我的构造函数之一?

为什么要编译此c ++程序?

为什么此C ++程序编译失败?

C ++为什么当“ 100%看起来像匹配”时出现错误“没有匹配功能”?

为什么闭包类型/ lambdas在C ++中没有默认构造函数

为什么C#中的通用参数没有构造函数与参数的约束?

为什么我的C#基本构造函数没有被调用?

为什么此代码段适用于C ++ 17,而编译器在使用C ++ 11时却抱怨呢?

为什么此C ++代码中的构造函数模棱两可,我该如何解决?

错误C2512:没有合适的默认构造函数-为什么在构造函数中初始化属性?

当未指定return语句时,为什么C ++没有默认构造返回值?

在constexpr函数中返回C字符串:为什么编译器没有警告?

为什么C ++ allow type对于std :: map没有默认构造函数,而没有std :: pair?

即使C ++编译器无法编译,为什么C编译器仍可以编译此代码?