「テスト」が通常のクラスの場合、以下の間に違いはありますか:
Test* test = new Test;
と
Test* test = new Test();
「テスト」が通常のクラスの場合、以下の間に違いはありますか:
Test* test = new Test;
と
Test* test = new Test();
コードの動作に実際に影響を与える可能性のある違いがあるため、知識を深めましょう。以下の多くは、 "Old New Thing" 記事に寄せられたコメントから抜粋したものです。
new 演算子によって返されるメモリが初期化されることもあれば、新しい型がPOD (plain old data)であるかどうか、または POD メンバーを含み、コンパイラが生成するデフォルト コンストラクタ。
推定:
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
- デフォルト ctor を呼び出す C をデフォルトで初期化します。
new C()
- デフォルトの ctor を呼び出す C を値で初期化します。したがって、C++ のすべてのバージョンでは、A が POD であるため、 と の間new A
に違いがあります。new A()
また、C++98 と C++03 では、 case の動作に違いがありnew B()
ます。
これは、気が狂ってしまうような 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の間で変更されました。方法と理由については、 MichaelBurrの説明を参照してください。
一般に、最初のケースではデフォルトの初期化があり、2番目のケースでは値の初期化があります。
例:int(PODタイプ)の場合:
int* test = new int
-初期化があり、*testの値は任意です。
int* test = new int()
-*testの値は0になります。
次の動作は、タイプテストによって異なります。さまざまなケースがあります。テストにはデフォルトのコンストラクターがあり、テストではデフォルトのコンストラクターが生成されています。テストにはPODメンバーが含まれていますが、PODメンバーではありません。
いいえ、同じです。ただし、次のような違いがあります。
Test t; // create a Test called t
と
Test t(); // declare a function called t which returns a Test
これは、基本的な C++ (および C) の規則によるものです。何かが宣言になる可能性がある場合、それは宣言です。
編集: PODおよび非PODデータに関する初期化の問題について、私は言われたことすべてに同意しますが、これらの問題は、新しいものまたはその他の方法で構築されたものにユーザー定義のコンストラクター。そのようなコンストラクターがある場合は、それが使用されます。賢明に設計されたクラスの 99.99% には、そのようなコンストラクターがあるため、問題は無視できます。
Test がコンストラクターが定義されたクラスであると仮定すると、違いはありません。後者の形式では、Test のコンストラクターが実行されていることが少し明確になりますが、それだけです。
Michael Burr の回答の補足として、以下にいくつかのサンプル コードを書きました。
#include <iostream>
struct A1 {
int i;
int j;
};
struct B {
int k;
B() : k(4) {}
B(int k_) : k(k_) {}
};
struct A2 {
int i;
int j;
B b;
};
struct A3 {
int i;
int j;
B b;
A3() : i(1), j(2), b(5) {}
A3(int i_, int j_, B b_): i(i_), j(j_), b(b_) {}
};
int main() {
{
std::cout << "Case#1: POD without ()\n";
A1 a1 = {1, 2};
std::cout << a1.i << " " << a1.j << std::endl;
A1* a = new (&a1) A1;
std::cout << a->i << " " << a->j << std::endl;
}
{
std::cout << "Case#2: POD with ()\n";
A1 a1 = {1, 2};
std::cout << a1.i << " " << a1.j << std::endl;
A1* a = new (&a1) A1();
std::cout << a->i << " " << a->j << std::endl;
}
{
std::cout << "Case#3: non-POD without ()\n";
A2 a1 = {1, 2, {3}};
std::cout << a1.i << " " << a1.j << " " << a1.b.k << std::endl;
A2* a = new (&a1) A2;
std::cout << a->i << " " << a->j << " " << a->b.k << std::endl;
}
{
std::cout << "Case#4: non-POD with ()\n";
A2 a1 = {1, 2, {3}};
std::cout << a1.i << " " << a1.j << " " << a1.b.k << std::endl;
A2* a = new (&a1) A2();
std::cout << a->i << " " << a->j << " " << a1.b.k << std::endl;
}
{
std::cout << "Case#5: user-defined-ctor class without ()\n";
A3 a1 = {11, 22, {33}};
std::cout << a1.i << " " << a1.j << " " << a1.b.k << std::endl;
A3* a = new (&a1) A3;
std::cout << a->i << " " << a->j << " " << a->b.k << std::endl;
}
{
std::cout << "Case#6: user-defined-ctor class with ()\n";
A3 a1 = {11, 22, {33}};
std::cout << a1.i << " " << a1.j << " " << a1.b.k << std::endl;
A3* a = new (&a1) A3();
std::cout << a->i << " " << a->j << " " << a1.b.k << std::endl;
}
return 0;
}
/*
output with GCC11.1(C++20)
Case#1: POD without ()
1 2
1 2
Case#2: POD with ()
1 2
0 0
Case#3: non-POD without ()
1 2 3
1 2 4
Case#4: non-POD with ()
1 2 3
0 0 4
Case#5: user-defined-ctor class without ()
11 22 33
1 2 5
Case#6: user-defined-ctor class with ()
11 22 33
1 2 5
*/