型名の後の括弧はnewと違いがありますか?
-
03-07-2019 - |
質問
「テスト」が通常のクラスである場合、次の間に違いがあります:
Test* test = new Test;
and
Test* test = new Test();
解決
コードの動作に実際に影響を与える可能性のある違いがあるため、心を引き締めましょう。以下の多くは、" Old Newもの"記事。
new演算子によって返されるメモリが初期化される場合があります。また、新しいタイプが POD(プレーンな古いデータ)、または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コンパイラでは、次が発生するはずです:
-
新しいA
-不定値 -
new A()
-ゼロ初期化 -
new B
-デフォルトの構成(B :: mは初期化されていません) -
new B()
-デフォルトの構成(B :: mは初期化されていません) -
新しいC
-デフォルトの構成(C :: mはゼロで初期化されます) -
new C()
-デフォルトの構成(C :: mはゼロで初期化されます)
C ++ 03準拠のコンパイラでは、次のように動作するはずです:
-
新しいA
-不定値 -
new A()
-value-initializeA。これはPODであるためゼロで初期化されます。 -
new B
-default-initializes(B :: mは初期化されないままにします) -
new B()
-デフォルトのctorはユーザー定義ではなくコンパイラによって生成されるため、すべてのフィールドをゼロで初期化するBを値で初期化します。 -
new C
-デフォルトのctorを呼び出すCをデフォルトで初期化します。 -
new C()
-デフォルトのctorを呼び出すCの値を初期化します。
C ++のすべてのバージョンでは、AはPODであるため、 new A
と new A()
には違いがあります。
そして、 new B()
の場合、C ++ 98とC ++ 03の動作に違いがあります。
これはC ++のほこりっぽいコーナーの1つであり、あなたを夢中にさせます。オブジェクトを構築するとき、時にはカレンが欲しい/必要な場合があります。時には絶対に持つことができず、時には重要ではありません。
他のヒント
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;
vs new Thingy();
の動作は、この場合C ++ 98とC ++ 2003の間で変更されました。方法と理由については、Michael Burrの説明を参照してください。
いいえ、それらは同じです。ただし、次の間に違いがあります。
Test t; // create a Test called t
and
Test t(); // declare a function called t which returns a Test
これは、基本的なC ++(およびC)ルールによるものです。何かが宣言になる可能性がある場合、それは宣言です。
編集: PODデータおよび非PODデータに関する初期化の問題について、これまで述べてきたことすべてに同意しますが、これらの問題は、 new'dまたはその他の方法で構築されたものには、ユーザー定義のコンストラクタはありません。そのようなコンストラクターがある場合は、それが使用されます。賢明に設計されたクラスの99.99%には、そのようなコンストラクターがあるため、問題は無視できます。
一般に、最初の場合はデフォルトの初期化があり、2番目の場合は値の初期化があります。
例: int(PODタイプ)の場合:
-
int * test = new int
-初期化があり、* testの値は任意です。 -
int * test = new int()
-* testの値は0です。
次の動作は、タイプテストに依存していました。 異なるケースがあります。テストにはデフォルトのコンストラクタが生成され、テストにはデフォルトのコンストラクタが生成され、テストにはPODメンバーが含まれ、PODメンバーは含まれません...
Testが定義されたコンストラクターを持つクラスであると仮定すると、違いはありません。後者の形式により、Testのコンストラクタが実行されていることが少し明確になりますが、それはそれについてです。