web-dev-qa-db-ja.com

型名の後の括弧はnewと違いますか?

'Test'が普通のクラスの場合、次のものに違いがありますか。

Test* test = new Test;

そして

Test* test = new Test();
947
David Read

実際にコードの動作に影響を与える可能性のある違いがあるので、ペダントにしましょう。以下の多くは、 "Old New Thing"の記事 に対するコメントから得られたものです。

New演算子によって返されるメモリが初期化されることもあれば、新しいタイプが POD( - plain old data)であるかどうかに依存しないこともあります 、またはそれがPODメンバーを含み、コンパイラー生成のデフォルトコンストラクターを使用しているクラスの場合。

  • C++ 1998には、ゼロとデフォルトの2種類の初期化があります。
  • C++ 2003では、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() - value-initialize A、これはPODであるためゼロ初期化です。

  • new B - default-initializes(B :: mを未初期化のままにします)

  • new B() - デフォルトのctorはユーザ定義とは対照的にコンパイラで生成されるため、Bはすべてのフィールドをゼロで初期化します。

  • new C - default-Cを初期化します。これはデフォルトのctorを呼び出します。

  • new C() - デフォルトのctorを呼び出すCの値を初期化します。

AはPODなので、C++のすべてのバージョンでnew Anew A()の違いがあります。

new B()の場合、C++ 98とC++ 03の間には振る舞いに違いがあります。

これはC++のほこりっぽいコーナーの1つです。オブジェクトを構築するとき、時にはあなたは親を欲しい/必要とします、時には絶対にそれらを持つことができない、そして時々それは問題ではありません。

908
Michael Burr

new Thing();は明示的にコンストラクタを呼び出したいことを明示していますが、new Thing;はコンストラクタが呼び出されていなくても構わないことを意味しています。

ユーザー定義のコンストラクタを持つ構造体/クラスで使用しても違いはありません。些細な構造体/クラス(例えば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();の動作は、C++ 98とC++ 2003の間で変更されました。方法と理由については、Michael Burrの説明を参照してください。

56
kfsone

いいえ、それらは同じです。しかし、違いがあります:

Test t;      // create a Test called t

そして

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

これは、基本的なC++(およびC)の規則によるものです。何かが宣言になる可能性がある場合、それは宣言です。

編集:PODデータとPOD以外のデータに関する初期化の問題について、私はこれまでに述べたことすべてに同意しますが、それを指摘しておきたいのです。これらの問題は、新しく作成されたものや別の方法で作成されたものにユーザー定義のコンストラクターがない場合にのみ適用されます。そのようなコンストラクタがある場合はそれが使用されます。賢明に設計されたクラスの99.99%にはそのようなコンストラクタがあるでしょう、そしてその問題は無視することができます。

18
anon

一般的に、最初の場合はdefault-initialization、2番目の場合はvalue-initializationがあります。

例:int(PODタイプ)の場合

  • int* test = new int - 初期化があり、* testの値はanyになります。

  • int* test = new int() - * testの値は0になります。

次の振る舞いはあなたの型テストに依存していました。テストにはデフォルトコンストラクタがあり、テストにはデフォルトのコンストラクタがあります。テストにはPODメンバがありますが、非PODメンバがあります。

16
bayda

Testが定義済みのコンストラクタを持つクラスであると仮定すると、違いはありません。後者の形式はTestのコンストラクタが実行されていることをもう少し明確にしますが、それはそれについてです。

10
Evan Shaw