2009-11-23 17 views
5
class MyClass 
{ 
}; 

void foo 
{ 
    MyClass arr[10]; 
} 

関数が返るときに配列オブジェクトの破壊の順序を知りたいと思います。オブジェクトの配列の破壊の順序

私はそれについて、それより効果的なC++を読んで、それは次のようにデストラクタがコンストラクタオーダーのとは逆 順序で呼び出されていることを述べている:誰が私にその理由を教えてもらえます

for(int i = 9 ; i >= 0 ;i--) 
{ 
    arr[i].MyClass::~MyClass(); 
} 

答えて

2

これは、C++のデストラクタ呼び出しの逆説の続きです。スタックに割り当てられたオブジェクトが破壊されると、RAIIを容易にするために逆の順序で行われます。これは配列要素のためには本当に必要ではありませんが(デフォルトのコンストラクタで構築されており、構築/破棄の順序は同じです)、一貫性のために同じものが使用されます。

+1

これらはすべてデフォルトのコンストラクタで構築され、構築/破壊の順序はどちらでも構いません。 "引数なしのコンストラクタはグローバル(クラス静的なものなど)にアクセスできるため、結果の配列には、私はあなたが何を意味するのかよく分かりません。どのオーダーでも意味があります.1つのオーダーだけが標準の12.6に準拠しています。インデックス内の別個の素因数の数の逆順で、基数7の桁の合計で決定される結び付き;-) –

0

おそらく、配列を構成するオブジェクトがスタックに配置される順序です。とにかく、好奇心を除いて、私は破壊命令を心配する理由はないと思うことができます。

+0

arr [n]がDTorの要素arr [n + 1]を参照すると、しかし、私の頭の上からは、現実世界の状況を考える必要はありません。 – foraidt

+0

@mxp。完全に同意しますが、配列のすべての要素が少なくとも配列の要素の1つである場合、配列の要素の破壊の順序はほんの小さな問題になります。 – jrbjazz

2

あなたがより効果的なC++でを参照している情報は、この場合のように、他のオブジェクトのカップルを含むオブジェクトに適用されます。上記の例で

class Foo { 
    private: 
    Bar bar_1; 
    Bar bar_2; 

    public: 
    Foo() : bar_1(), bar_2() {} 
}; 

、あなたはBAR_1は、最初に構築していますよ、続いてbar_2。クラスFooのオブジェクトが破壊されると、bar_2が最初に破棄され、次にbar_1が破壊されます。それがScott Meyersが言及しているものです。

バーの配列は、コンパイラが破壊する必要がある別のオブジェクトであるため、クラス内の他のオブジェクトのコンテキストで配列が破棄されると、破壊の順序が影響を受けます。

配列の要素がどの順序で破棄されるかについては、それが実装に依存する場合はあまり驚くことではありません。また、ここで最適化を行うこともあります(たとえば、PODアレイは、PODだけで構成されているオブジェクトのように、メモリを解放するだけで破棄できます)。上記のすべてが、配列の要素が破壊される順序に影響する可能性があります。

私は、配列要素が破壊される順番を知る必要があるのを知りたいと考えています(技術的な好奇心は別として、これはIMHOの有効な理由です)。配列の要素間に依存関係があるため、データ構造が再検討される必要があると私は考えています。

1

すべての注文は、本当に行います。 2つの明白な選択肢は、もちろん順番にも逆の順でもあります。しかし、この場合、どのコンパイラメーカーも、この実装依存のままにすることは価値があると考えていませんでした。したがって、逆順を命じる選択がなされました(通常のLIFOの振る舞いを拡張しながら、シャープトゥースが述べられています)。

0

あなたはマイヤーの本のどのページを引用していませんが、私はティモ・ガウスそのコンストラクタを参照しているように聞こえ、継承に従ってデストラクタが呼び出されます。

オブジェクトインスタンスの配列の場合、オブジェクトが破棄される順序は構築順序の逆です。次のコードに示すように、これは簡単に確認できます。クラス変数は作成されたインスタンスの総数を追跡し、各オブジェクトのデータメンバーは自身の数を追跡します。コンストラクタとデストラクタはメッセージを出力するので、実行すると何が起こるかを正確に見ることができます。

テストコードは、構築時にオブジェクトの数を0から9まで、次にインスタンスを破棄するときに9から0にオブジェクトの数を出力します。 (しばしばそうであるように)私は、これは実装の詳細ではないことが100%わからないよう

#include <iostream> 

class MyClass 
{ 
public: 

    MyClass() 
    { 
     mCounter = kInstanceCount++; 
     std::cout << "+++ MyClass() " << mCounter << std::endl; 
    } 

    ~MyClass() 
    { 
     std::cout << "--- MyClass() " << mCounter << std::endl; 
    } 

private: 
    unsigned   mCounter; 
    static unsigned  kInstanceCount; 
}; 

unsigned MyClass::kInstanceCount = 0; 

int main() 
{ 
    MyClass arr[10]; 
    return 0; 
} 

あなたは、C++標準をチェックする必要があります(これは、Mac OS X上でg++-4.2でテストされました)この場合、この動作に頼る必要はありません。

また、実際のオブジェクトインスタンスのスタックベースの配列を作成することはあまり一般的ではないことにも注意してください。 std::vectorを使用している可能性が高く、ヒープ割り当てオブジェクトのスマートポインタを使用する可能性があります。

関連する問題