2012-06-18 6 views
8

可能性の重複を返すときにデストラクタが呼び出されない:
Why is the destructor not called for the returned object from the function?
は、ローカル・インスタンスに

は、私はいくつかのC++のコードを(下)書いて、GCC 4.6でそれをコンパイルし、それが正常に実行されました。しかし、createA()から返ってきたときに、デストラクタclassAが呼び出されない理由はわかりません。

cacreateA()のローカル変数(つまりスタック上にある)なので、関数から戻るときにそのデストラクタを呼び出す必要があります。しかし実際には、デストラクタはmain関数から戻るときに一度しか呼び出されません。

また、ローカルインスタンスを返すことは、このテストでは常に正常に動作します。私は、フレームが返された後にポップアウトされたときにスタックフレームにローカルインスタンスを返すのが安全かどうか疑問に思います。

これは私のコードです:

#include <iostream> 
#include <string.h> 

class classA 
{ 
public: 
    classA() { len = 0; v = 0; } 

    classA(int a) 
    { 
     len = a; 
     v = new int[a]; 
     for (int i = 0; i < a; i++) 
      v[i] = 2*i; 
    } 

    ~classA() 
    { 
     if (v) 
      { 
      memset(v, 0, len * sizeof(int)); 
      delete [] v; 
     } 
    } 

    int *v; 
    int len; 
}; 

classA createA(int a) 
{ 
    classA ca(a); 
    return ca; 
} 

using namespace std; 

int main() 
{ 
    int a = 10; 
    classA ca = createA(a); 
    classA *pca = &ca; 
    for (int i = 0; i < a; i++) 
     cout << pca->v[i]; 
    cout << endl; 
    return 0; 
} 

答えて

14

これは、戻り値の最適化と呼ばれています。

つまり、コンパイラはコードを最適化するためにオブジェクトのコピーを返す必要はありません。 CAの

必ずしも

ていない[...]即ちスタックに、ローカル変数です。 caは、余分なコピーを防ぐために呼び出しコンテキストで直接作成することができます。 コピーエリジョンは、コンパイラが自由に実行できる唯一の最適化であり、期待される動作を変更することができます。

+1

また、より一般的な名前:コピーelisionになります。 –

+1

実際、これは* Named * Return Value Optimizationと呼ばれる特殊なRVOのケースです。 – dirkgently

+0

おかげでGrigore。そして、別の質問があります:ローカルクラス変数を返すのが安全ならば。この手法、RVO、C++仕様、またはコンパイラの最適化の仕組みですか? –

関連する問題