1066

「テスト」が通常のクラスの場合、以下の間に違いはありますか:

Test* test = new Test;

Test* test = new Test();
4

7 に答える 7

998

コードの動作に実際に影響を与える可能性のある違いがあるため、知識を深めましょう。以下の多くは、 "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 - デフォルト初期化 (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 つです。オブジェクトを構築するとき、括弧が必要/必要な場合もあれば、絶対に持てない場合もあり、問題にならない場合もあります。

于 2009-03-06T21:01:23.543 に答える
84

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の説明を参照してください。

于 2013-02-15T19:57:41.420 に答える
20

一般に、最初のケースではデフォルトの初期化があり、2番目のケースでは値の初期化があります。

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

  • int* test = new int-初期化があり、*testの値は任意です。

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

次の動作は、タイプテストによって異なります。さまざまなケースがあります。テストにはデフォルトのコンストラクターがあり、テストではデフォルトのコンストラクターが生成されています。テストにはPODメンバーが含まれていますが、PODメンバーではありません。

于 2009-03-06T20:00:19.603 に答える
20

いいえ、同じです。ただし、次のような違いがあります。

Test t;      // create a Test called t

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

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

編集: PODおよび非PODデータに関する初期化の問題について、私は言われたことすべてに同意しますが、これらの問題は、新しいものまたはその他の方法で構築されたものにユーザー定義のコンストラクター。そのようなコンストラクターがある場合は、それが使用されます。賢明に設計されたクラスの 99.99% には、そのようなコンストラクターがあるため、問題は無視できます。

于 2009-03-06T19:42:10.707 に答える
10

Test がコンストラクターが定義されたクラスであると仮定すると、違いはありません。後者の形式では、Test のコンストラクターが実行されていることが少し明確になりますが、それだけです。

于 2009-03-06T19:42:34.013 に答える
0

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
*/
于 2021-09-01T09:16:28.407 に答える