2009-09-01 7 views
2

C++では、スタックに割り当てられたオブジェクトに対してデストラクタが確実に呼び出されますか?スタック割り当てオブジェクトに対してデストラクタが呼び出されるメカニズムは何ですか?

class MyClass { 
public: 

    ~MyClass() 
    { 
    std::cout<<"Destructor called."<<std::endl; 
    } 

    MyClass() 
    { 
    std::cout<<"Constructor called."<<std::endl; 
    } 

}; 

.................................................................... 

//Limit scope for example 
{ 
    MyClass instance; 
} 

コンストラクタとデストラクタの両方と呼ばれている:何が次のように私が動的メモリを割り当てデストラクタ関数(またはそれへのポインタ)に起こります。何が起きてる?

+0

インスタンスオブジェクトの名前です。 instance()は、クラスのno引数ctorへの単なる呼び出しです。この場合、括弧は不要ですが、確かにinstance()というメソッドへの呼び出しではありません。 – dicroce

+5

ダイナミックメモリの割り当てが表示されません。 –

答えて

7

コンパイラはオブジェクトのデストラクタへの呼び出しを適切な位置に挿入します。

1

オブジェクトを作成しているので、コンストラクタが呼び出されます。デストラクタは、そのオブジェクトをクリーンアップするために呼び出されます。 C++では、スタック上に宣言されたオブジェクトは、そのスコープが消えたときに自動的にクリーンアップされることを覚えておいてください。

3

変数が作成されるとすぐにコンストラクタが呼び出されます。デストラクタに関しては、コンパイラはスコープの終わりにデストラクタを呼び出すコードを発行します。これを感じるには、 'goto'やswitch/caseを使ってスコープを早めに終了し、コンパイラが不平を言うのを見てください。

+1

"コンストラクタは、変数が作成されるとすぐに呼び出されます。"オブジェクトの作成はコンストラクターが呼び出されたときに行われるので、これは不思議ではありません。変数OTOHのメモリーは、先に提供される場合があります。 – sbi

+1

私が知る限り、スコープをgotoで終了することはできますが、コンパイラはオブジェクトがスコープから外れることをまだ知っています。あなたがすることが許されていないものは、goto/switchを使ってオブジェクト宣言(構築)をステップオーバーすることです。 – UncleBens

+0

@UncleBens:これを "オブジェクト定義"にします。そうでなければ、あなたは正しいです。 (私は速読し、マナグの答えでこのエラーを見たこともありませんでした。) – sbi

3

はい、コンストラクタとデストラクタの両方が呼び出されます。さらに重要なのは、

{ 
MyClass instance; 
throw "exception"; 
} 

この例では、デストラクタも呼び出されます。そのため、私は常に自分のオブジェクトをスタックに割り当てることを好みます(または少なくとも、スタック割り当てのガーディアンで動的割り当てをラップする)。

4

この

{ 
    int i; 
} 

が作成され、自動的にi破壊し、あなたのだろうなぜあなたは不思議ではないでしょうか? C++では、組み込み型と同じように動作する型を作成できるようにするために多くのことが行われています。そして、ちょうど組み込み型と同じように、C++(他に比べて、たとえば、JavaやC#)で、この

{ 
    MyClass instance; 
} 

はちょうどnullにバインドされる可能性があります参照またはいくつかの実際のオブジェクトを定義していません。それは実際のオブジェクトを作成します。

オブジェクトの作成には2つのステップがあります。まず、スコープに入ると、生のメモリが提供されます。次に(オブジェクト定義に遭遇したとき)コンストラクタが呼び出されます。組み込み型の場合、コンストラクターは呼び出されません。組み込み変数を初期化しないと、それはランダムな値を持ちます。 (実際には、ステップ1で提供されたメモリにビットパターンがあったとしても)オブジェクトの削除も2つのステップで行われます。まず、デストラクタが呼び出されます(組み込み関数ではない)。ランタイムシステム。

(スタック変数のためのメモリを提供し、削除すると、通常はレジスタをデクリメント/ incementingほど安くであることに注意してください。)

0

まあ、それはちょうど、コンストラクタの後にデストラクタを呼び出していませんでした。
プログラムを終了しようとしたときに呼び出されます。

int main() { 
    MyClass obj; 
    cout<<"testing....1"<<endl; 
    cout<<"testing....2"<<endl; 
    return 0; 
} 

ANS:

Constructor called. 
testing....1 
testing....2 
Destructor called. 
+1

プログラムが終了しようとしているときにデストラクタを呼び出さない。デストラクタは、スタックオブジェクトが有効範囲外になると呼び出されます。あなたがメインでこれをやっているので、それらの2つが同時に起こります。 –

関連する問題