メンバーコンストラクターとデストラクタコールの順序


120

ああC ++の教祖、私はあなたの知恵を求めています。私に標準語を話し、C ++が次のプログラムを保証するかどうかを教えてください:

#include <iostream>
using namespace std;

struct A
{
    A() { cout << "A::A" << endl; }
    ~A() { cout << "A::~" << endl; }
};

struct B
{
    B() { cout << "B::B" << endl; }
    ~B() { cout << "B::~" << endl; }
};

struct C
{
    C() { cout << "C::C" << endl; }
    ~C() { cout << "C::~" << endl; }
};

struct Aggregate
{
    A a;
    B b;
    C c;
};

int main()
{
    Aggregate a;
    return 0;
}

常に生成されます

A::A
B::B
C::C
C::~
B::~
A::~

つまり、メンバーは宣言の順序で初期化され、逆の順序で破棄されることが保証されていますか?


8
これは、クラスが大きくなり、おかしくならない場合に、微妙なバグのかなり一般的な原因です。50のデータメンバーがあり、それらの多くがコンストラクター初期化子リストで初期化されている場合、構築の順序が初期化子リストの順序であると簡単に想定できます。結局のところ、コード作成者はリストを注意深く注文しています...そうではありませんか?
Permaquid 2010

回答:


139

つまり、メンバーは宣言の順序で初期化され、逆の順序で破棄されることが保証されていますか?

はい、両方に。12.6.2を参照

6初期化は次の順序で行われます。

  • まず、以下で説明する最も派生したクラスのコンストラクターについてのみ、仮想基本クラスは、基本クラスの有向非循環グラフの深さ優先の左から右へのトラバーサルに現れる順序で初期化されます。 -to-right」は、派生クラスbase-specifier-listでの基本クラス名の出現順序です。

  • 次に、直接基底クラスは、(mem-initializersの順序に関係なく)base-specifier-listに出現する宣言順に初期化されます。

  • 次に、静的でないデータメンバーは、クラス定義で宣言された順序で初期化されます(これも、mem-initializerの順序に関係ありません)。

  • 最後に、コンストラクタ本体の複合文が実行されます。[注:宣言の順序は、ベースとメンバーのサブオブジェクトが初期化の逆の順序で確実に破棄されるように義務付けられています。—エンドノート]


2
私が正しく覚えていれば、両方ともそうです...それをスタックと考えてください。最初にプッシュされ、最後にポップされました。そのため、最初のインスタンスをインスタンス化すると、スタックの順にメモリにプッシュされます。次に、2番目がプッシュされ、3番目が2番目、というように続きます。次に、インスタンスを破棄するとき、プログラムは最初に破棄するもの、最後にプッシュされたものを探します。しかし、私はこのように説明するのは間違っているかもしれませんが、C / C ++とASMを行うときに私がそれを学んだ方法です。
Marcouiller氏、2010

29

はい、それらは(非静的メンバーです)です。初期化(構築)については12.6.2 / 5を、破棄については12.4 / 6を参照してください。


10

はい、標準では、オブジェクトが作成されたときとは逆の順序で破壊されることが保証されています。その理由は、あるオブジェクトが別のオブジェクトを使用する可能性があるため、それに依存しているためです。考慮してください:

struct A { };

struct B {
 A &a;
 B(A& a) : a(a) { }
};

int main() {
    A a;
    B b(a);
}

場合はa前に破壊したb後、b無効なメンバ参照を保持します。作成された順序とは逆の順序でオブジェクトを破棄することにより、正しい破棄が保証されます。


このルールがスコープメンバーの破棄順序にも適用されるとは、私は実際には考えていませんでした。
yano

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.