7

一般的な質問がありますが、それはコンパイラ固有のものかもしれません。コンストラクターが呼び出される条件に興味があります。具体的には、速度が最適化されたリリースモード/ビルドでは、オブジェクトをインスタンス化するときに、コンパイラによって生成されたコンストラクタまたは空のコンストラクタが常に呼び出されますか?

class NoConstructor  
{  
    int member;  
};  

class EmptyConstructor  
{  
    int member;  
};

class InitConstructor  
{  
    InitConstructor()  
        : member(3)   
    {}  
    int member;  
};

int main(int argc, _TCHAR* argv[])  
{  
    NoConstructor* nc = new NoConstructor(); //will this call the generated constructor?  
    EmptyConstructor* ec = new EmptyConstructor(); //will this call the empty constructor?  
    InitConstructor* ic = new InitConstructor(); //this will call the defined constructor  

    EmptyConstructor* ecArray = new EmptyConstructor[100]; //is this any different?
}

私は多くの検索を行い、VisualStudioで生成されたアセンブリコードを調べるのに時間を費やしました。ただし、リリースビルドでフォローするのは難しい場合があります。

要約:コンストラクターは常に呼び出されますか?もしそうなら、なぜですか?

これはコンパイラに大きく依存することは理解していますが、確かに共通のスタンスがあります。あなたが引用できるどんな例/情報源も本当にありがたいです。

4

5 に答える 5

15

オブジェクトをインスタンス化するときに、コンパイラーが生成したコンストラクター/空のコンストラクターが常に呼び出されますか?

いいえ。クラスがいわゆる「POD」(単純な古いデータ)である場合、コンパイラーによって生成されたコンストラクターが常に呼び出されるとは限りません。

具体的には、次の2つの場合は呼び出されません。

struct Pod {
    int x;
};

int main() {
    Pod pod;
    std::cout << pos.x << std::endl; // Value undefined.

    Pod pod2 = Pod(); // Explicit value initialization.


    Pod* pods = new Pod[10];
    // Values of `pods` undefined.

    Pod* pods2 = new Pod[10](); // Explicit value initialization.
}

正確に型がPODである場合の条件は、少し注意が必要です。C++FAQには素晴らしい内訳があります。

于 2011-02-23T21:50:40.077 に答える
10

論理的には、コンストラクターが呼び出されます。生成されたコードでは、コンストラクターが何もしない場合、コンパイラーが最適化に非常に苦手で、ただ戻るものへの呼び出しを挿入しない限り、コンストラクターにさかのぼることができる命令はありません。

于 2011-02-23T21:49:29.007 に答える
5

最適化モードで、クラスまたは構造体がPOD(PODタイプのみ)でコンストラクターが指定されていない場合、本番品質のC ++コンパイラーは、コンストラクターの呼び出しをスキップするだけでなく、コンストラクターを生成しません。

クラスにコンストラクターを呼び出す必要のある非PODメンバーが含まれている場合、コンパイラーはメンバーのコンストラクターを呼び出すデフォルトのコンストラクターを生成します。しかし、それでも-PODタイプは初期化されません。つまり、明示的に初期化しないmemberと、そこにゴミが発生する可能性があります。

コンパイラー/リンカーにLTOがあれば、すべてが空想にふけることができます。

それが役に立てば幸い!そして、最初にプログラムを動作させ、次にプロファイラーを使用して遅い場所を検出し、それを最適化します。時期尚早の最適化は、コードを読めなくし、多くの時間を浪費するだけでなく、まったく役に立たない可能性があります。最初に何を最適化するかを知っておく必要があります。

これがあなたの例(x86_64、gcc 4.4.5)のコードの分解です:

main:
    subq    $8, %rsp
    movl    $4, %edi
    call    _Znwm
    movl    $4, %edi
    movl    $0, (%rax)
    call    _Znwm
    movl    $4, %edi
    movl    $0, (%rax)
    call    _Znwm
    movl    $400, %edi
    movl    $3, (%rax)
    call    _Znam
    xorl    %eax, %eax
    addq    $8, %rsp
    ret

ご覧のとおり、コンストラクターはまったく呼び出されません。クラスはまったくありません。すべてのオブジェクトは4バイトの整数です。

MSコンパイラでは、YMMV。したがって、分解を自分で確認する必要があります。しかし、結果は似ているはずです。

幸運を!

于 2011-02-23T21:58:36.260 に答える
1

特定のクラスまたは構造体タイプは、C++ではPOD「プレーンオールドデータ」と呼ばれます。これらの型には、呼び出されるコンストラクターはありません。

PODになるためのルールは、調べる必要があるほど重要ですが、要約すると、プリミティブデータ型のみが含まれ、コンストラクターは定義されていません。

于 2011-02-23T21:50:50.647 に答える
0

あなたのサンプルはあまり良くありません、あなたはpublicサンプルクラスのキーワードを逃しました、そしてさらにあなたの例でCLASS * class = new CLASS();は代わりに書くことによってゼロ初期化を強制しますCLASS * class = new CLASS;

あなたがそれを置くようにコードで-ゼロ初期化はそれが標準によって要求されるように常に実行されます。好きなように呼び出すことができますが、標準のルールを保証するコードがあります。

この物議を醸すサンプルコードを表示せずに質問した場合、正しい答えは-だけcompiler specificです。

于 2011-02-23T22:10:33.510 に答える