C++ 类型名称后面的括号与 new 有区别吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/620137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:17:37  来源:igfitidea点击:

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

c++constructorinitializationnew-operatorc++-faq

提问by David Read

If 'Test' is an ordinary class, is there any difference between:

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

Test* test = new Test;

and

Test* test = new Test();

采纳答案by Michael Burr

Let's get pedantic, because there are differences that can actually affect your code's behavior. Much of the following is taken from comments made to an "Old New Thing" article.

让我们变得迂腐,因为有些差异实际上会影响您的代码行为。以下大部分内容摘自对“旧的新事物”文章的评论

Sometimes the memory returned by the new operator will be initialized, and sometimes it won't depending on whether the type you're newing up is a POD (plain old data), or if it's a class that contains POD members and is using a compiler-generated default constructor.

有时 new 操作符返回的内存将被初始化,有时它不会取决于您要更新的类型是POD (plain old data),还是包含 POD 成员并正在使用的类编译器生成的默认构造函数。

  • In C++1998 there are 2 types of initialization: zero and default
  • In C++2003 a 3rd type of initialization, value initialization was added.
  • 在 C++1998 中有两种类型的初始化:零和默认
  • 在 C++2003 中,添加了第三种类型的初始化,即值初始化。

Assume:

认为:

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

In a C++98 compiler, the following should occur:

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

  • new A- indeterminate value
  • new A()- zero-initialize

  • new B- default construct (B::m is uninitialized)

  • new B()- default construct (B::m is uninitialized)

  • new C- default construct (C::m is zero-initialized)

  • new C()- default construct (C::m is zero-initialized)
  • new A- 不确定值
  • new A()- 零初始化

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

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

  • new C- 默认构造(C::m 是零初始化的)

  • new C()- 默认构造(C::m 是零初始化的)

In a C++03 conformant compiler, things should work like so:

在符合 C++03 的编译器中,事情应该像这样工作:

  • new A- indeterminate value
  • new A()- value-initialize A, which is zero-initialization since it's a POD.

  • new B- default-initializes (leaves B::m uninitialized)

  • new B()- value-initializes B which zero-initializes all fields since its default ctor is compiler generated as opposed to user-defined.

  • new C- default-initializes C, which calls the default ctor.

  • new C()- value-initializes C, which calls the default ctor.
  • new A- 不确定值
  • new A()- 值初始化 A,这是零初始化,因为它是一个 POD。

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

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

  • new C- 默认初始化 C,它调用默认的构造函数。

  • new C()- 值初始化 C,它调用默认的构造函数。

So in all versions of C++ there's a difference between new Aand new A()because A is a POD.

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

And there's a difference in behavior between C++98 and C++03 for the case new B().

对于 case ,C++98 和 C++03 之间的行为存在差异new B()

This is one of the dusty corners of C++ that can drive you crazy. When constructing an object, sometimes you want/need the parens, sometimes you absolutely cannot have them, and sometimes it doesn't matter.

这是 C++ 尘土飞扬的角落之一,可以让您发疯。在构造对象时,有时您想要/需要括号,有时您绝对不能拥有它们,有时这无关紧要。

回答by kfsone

new Thing();is explicit that you want a constructor called whereas new Thing;is taken to imply you don't mind if the constructor isn't called.

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

If used on a struct/class with a user-defined constructor, there is no difference. If called on a trivial struct/class (e.g. struct Thing { int i; };) then new Thing;is like malloc(sizeof(Thing));whereas new Thing();is like calloc(sizeof(Thing));- it gets zero initialized.

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

The gotcha lies in-between:

问题介于两者之间:

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

The behavior of new Thingy;vs new Thingy();in this case changed between C++98 and C++2003. See Michael Burr's explanation for how and why.

在这种情况下,new Thingy;vs的行为new Thingy();在 C++98 和 C++2003 之间发生了变化。请参阅 Michael Burr 对方法和原因的解释。

回答by kfsone

No, they are the same. But there is a difference between:

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

Test t;      // create a Test called t

and

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

This is because of the basic C++ (and C) rule: If something can possibly be a declaration, then it is a declaration.

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

Edit:Re the initialisation issues regarding POD and non-POD data, while I agree with everything that has been said, I would just like to point out that these issues only apply if the thing being new'd or otherwise constructed does not have a user-defined constructor. If there is such a constructor it will be used. For 99.99% of sensibly designed classes there will be such a constructor, and so the issues can be ignored.

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

回答by bayda

In general we have default-initialization in first case and value-initialization in second case.

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

For example: in case with int (POD type):

例如:如果使用 int(POD 类型):

  • int* test = new int- we have any initialization and value of *test can be any.

  • int* test = new int()- *test will have 0 value.

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

  • int* test = new int()- *test 将有 0 值。

next behaviour depended from your type Test. We have defferent cases: Test have defult constructor, Test have generated default constructor, Test contain POD member, non POD member...

下一个行为取决于您的类型测试。我们有不同的情况:测试有默认构造函数,测试生成默认构造函数,测试包含 POD 成员,非 POD 成员......

回答by Evan Shaw

Assuming that Test is a class with a defined constructor, there's no difference. The latter form makes it a little clearer that Test's constructor is running, but that's about it.

假设 Test 是一个具有已定义构造函数的类,则没有区别。后一种形式更清楚地表明 Test 的构造函数正在运行,但仅此而已。