2012-03-02 3 views
0

わかっているように、コンストラクタとデストラクタはペアになります。C++:関数によって返されたクラス参照のため、コンストラクタとデストラクタがペアになっていません

しかし、次のコードはそのように動作しません。 コンストラクタは2回呼び出されますが、デストラクタは1回だけ呼び出されます。

{ 
    Animal ahe; 
    ahe = CreateAnimal(); 
} 

詳細については、お読みください。

int main(int argc, char* argv[]) 
{ 
    Animal ahe; 

    return 0; 
} 

動物のコンストラクタとデストラクタは一度だけ呼び出されます両方ことが期待されます。

が動物という名前のクラスがあり、私たちは次のコードがあるとします。 私がコードを実行すると、それは私が期待したものとまったく同じように動作します。

しかし、関数によってAnimalの参照が返されたときには、次のコードについてはかなり奇妙に見えます。 コードを実行すると、コンストラクタは2回呼び出されますが、デストラクタは1回だけ呼び出されます。

#include "stdafx.h" 
#include "stdio.h" 
#include "iostream.h" 

class Animal 
{ 
public: 
    Animal(); 
    Animal(long age); 

    ~Animal(); 
private: 
    long m_age; 
}; 

Animal::~Animal() 
{ 
    cout<<"Animal::~Animal()"<<"age="<<m_age<<endl; 
} 
Animal::Animal() 
{ 
    m_age = 1; 
    cout<<"Animal::Animal()"<<"age="<<m_age<<endl; 
} 

Animal::Animal(long age) 
{ 
    m_age = age; 
    cout<<"Animal::Animal()"<<"age="<<m_age<<endl; 
} 

Animal& CreateAnimal() 
{ 
    Animal *pAnimal = new Animal(5); 

    return *pAnimal; 
} 

int main(int argc, char* argv[]) 
{ 
    Animal ahe; 

    ahe = CreateAnimal(); 

    return 0; 
} 

//出力

Animal::Animal()age=1 
Animal::Animal()age=5 
Animal::~Animal()age=5 

明らかに、最初のオブジェクトのデストラクタが呼び出されていない、なぜ? Animalに、そのデストラクタで解放する必要のあるリソースがたくさんある場合は、問題が深刻な場合があります。

答えて

6

newを介してCreateAnimalでオブジェクトを作成していますが、これはコンストラクタを呼び出しますが、newを介して作成されたオブジェクトのデストラクタを明示的に呼び出す必要があります。 コードは実際には期待通りに動作しています。コンストラクタは両方のオブジェクトに対して呼び出されますが、最初のオブジェクトがスタック上にあるときにスコープから外れると、デストラクタは呼び出されますが、newを使って作成されたオブジェクトは削除されません。削除を明示的に呼び出す必要があります。

デストラクターが呼び出されたオブジェクトのコピーです。 ahe = CreateAnimal()を代入すると、あなたはすべてのオブジェクトに対して削除を呼び出すことを覚えたくない場合AHEを参照

Animal ahe; // -> constructor called for object on stack 
    ahe = CreateAnimal(); // -> constructor called due to new call and ahe created in previous //line replaced with the object created via new 
    } // main method ends, ahe goes out of scope and it's destructor is called but since //it now contains a copy of the object created via new, it prints 5 

ないようスタック上に作成されたコピーはちょうどauto_ptrsを使用して新しいを使用して作成しました。

+0

+1 CreateAnimalでオペレータの新しい呼び出しをすばやく見つけることができます。 – stinky472

+0

しかし、コードの出力は、新しいISを介して作成されたオブジェクトのデストラクタを呼び出します。デストラクタが呼び出されていない最初のオブジェクト(Animal ahe;)です。 – Jack

+2

スマートポインタやセマンティクスに言及する価値があります。また、関数内のフリーストアに割り当てられたオブジェクトへの参照を決して返すことは絶対にありません。それは、インターフェイス全体を変更せずに修正できない、さらに隠されたメモリリークであるため、クライアントが削除することを期待するポインタを返すよりもさらに悪いことです。 – stinky472

関連する問題