协慌网

登录 贡献 社区

类型名称后的括号是否与 new 有区别?

如果'Test' 是一个普通的类,那么之间有什么区别:

Test* test = new Test;

Test* test = new Test();

答案

让我们变得迂腐,因为存在实际上会影响代码行为的差异。以下大部分内容来自对“Old New Thing” 文章的评论

有时新运算符返回的内存将被初始化,有时它不会取决于您正在新建的类型是POD(普通旧数据) ,还是它是一个包含 POD 成员且正在使用的类编译器生成的默认构造函数。

  • 在 C ++ 1998 中,有两种类型的初始化:零和默认
  • 在 C ++ 2003 第三种类型的初始化中,添加了值初始化。

假设:

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() - value-initialize A,它是零初始化,因为它是 POD。

  • new B - 默认初始化(离开 B :: m 未初始化)

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

  • new C - default-initializes C,调用默认的 ctor。

  • new C() - value-initializes C,调用默认的 ctor。

因此,在所有版本的 C ++ 中, new Anew A()之间存在差异,因为 A 是 POD。

对于new B() ,C ++ 98 和 C ++ 03 之间的行为有所不同。

这是 C ++ 尘封的角落之一,可以让你发疯。在构造一个物体时,有时候你需要 / 需要它们,有时候你绝对不能拥有它们,有时它们并不重要。

new Thing();明确表示你想要一个名为new Thing;的构造函数new Thing;被认为暗示你不介意是否没有调用构造函数。

如果在具有用户定义构造函数的 struct / class 上使用,则没有区别。如果调用一个简单的 struct / class(例如struct Thing { int i; }; )那么就是new Thing;就像malloc(sizeof(Thing));new Thing();就像calloc(sizeof(Thing)); - 初始化为零。

问题在于:

struct Thingy {
  ~Thingy(); // No-longer a trivial class
  virtual WaxOn();
  int i;
};

new Thingy;的行为new Thingy; vs new Thingy();在这种情况下,在 C ++ 98 和 C ++ 2003 之间进行了更改。请参阅 Michael Burr 关于如何以及为何的解释。

不,他们是一样的。但是有以下区别:

Test t;      // create a Test called t

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

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

编辑:重新解决有关 POD 和非 POD 数据的初始化问题,虽然我同意所有已经说过的内容,但我只想指出这些问题仅适用于新的或以其他方式构建的内容没有用户定义的构造函数。如果有这样的构造函数,它将被使用。对于 99.99%的合理设计类,将会有这样的构造函数,因此可以忽略这些问题。