关于c ++:类型名称后面的括号是否与new有区别?

Do the parentheses after the type name make a difference with new?

如果"测试"是一个普通类,那么以下两者之间是否存在任何差异:

1
Test* test = new Test;

1
Test* test = new Test();


让我们学点书生气吧,因为有一些差异实际上会影响代码的行为。以下大部分内容摘自对一篇"旧的新事物"文章的评论。

有时,新操作符返回的内存将被初始化,有时它将不取决于您正在更新的类型是POD(纯旧数据),或者它是一个包含POD成员的类,并且使用编译器生成的默认构造函数。

  • 在C++ 1998中,初始化有2种类型:零和默认值。
  • 在C++ 2003中进行了第三种初始化,增加了值初始化。

假设:

1
2
3
struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

在C++ 98编译器中,应该发生以下情况:

  • new A不定值
  • new A()零初始化

  • new B—默认构造(b::m未初始化)

  • new B()—默认构造(b::m未初始化)

  • new C—默认构造(c::m初始化为零)

  • new C()—默认构造(c::m初始化为零)

在C++ 03兼容编译器中,事情应该是这样工作的:

  • new A不定值
  • new A()值初始化a,这是零初始化,因为它是一个pod。

  • new B-默认初始化(保留b::m未初始化)

  • new B()值初始化b,因为它的默认ctor是由编译器生成的,而不是由用户定义的,所以b为零初始化所有字段。

  • new C—默认初始化c,它调用默认ctor。

  • new C()值初始化c,它调用默认ctor。

因此,在所有版本的C++中,EDCOX1与2的EDCOX1和EDCOX1之间的区别是3,因为A是POD。

在EDCOX1与5的情况下,C++ 98和C++ 03之间的行为有差异。

这是C++的一个尘土飞扬的角落,可能会让你发疯。当构造一个对象时,有时你想要/需要parens,有时你绝对不能拥有它们,有时它并不重要。


new Thing();明确表示需要调用构造函数,而new Thing;则表示不介意是否调用构造函数。

如果在具有用户定义构造函数的结构/类上使用,则没有区别。如果调用一个普通的结构/类(如struct Thing { int i; };),那么new Thing;就像malloc(sizeof(Thing));,而new Thing();calloc(sizeof(Thing));,它得到零初始化。

Gotcha介于:

1
2
3
4
5
struct Thingy {
  ~Thingy(); // No-longer a trivial class
  virtual WaxOn();
  int i;
};

EDCX1与24的EDCOX1,25的行为在这种情况下在C++ 98和C++ 2003之间发生了变化。查看迈克尔·伯尔的解释,了解如何以及为什么。


不,它们是一样的。但两者之间存在差异:

1
Test t;      // create a Test called t

1
Test t();   // declare a function called t which returns a Test

这是因为基本的C++(和C)规则:如果某事物可能是一个声明,那么它就是一个声明。

编辑:重新初始化POD和非POD数据的问题,虽然我同意所说的一切,但我想指出的是,这些问题仅适用于新的或以其他方式构建的对象没有用户定义的构造函数的情况。如果有这样的构造器,将使用它。对于99.99%设计合理的类,会有这样一个构造函数,因此可以忽略这些问题。


一般来说,我们在第一种情况下有默认初始化,在第二种情况下有值初始化。

例如:如果是int(pod类型):

  • int* test = new int—我们有任何初始化,并且*test的值可以是any。

  • int* test = new int()-*测试值为0。

下一个行为取决于您的类型测试。我们有不同的例子:测试有默认的构造函数,测试生成了默认的构造函数,测试包含pod成员,非pod成员…


假设测试是一个具有已定义构造函数的类,则没有区别。后一种形式使测试的构造函数正在运行变得更加清晰,但这就是问题所在。