このオブジェクトを使用して、次のことを理解してください。
class Foo
{
public:
Foo(int x): m_x(x)
{
std::cout << "Constructed Object: " << m_x << ")\n";
}
Foo(Foo const& c): m_x(c.m_x+100)
{
std::cout << "Copied Object: " << m_x << ")\n";
}
~Foo()
{
std::cout << "Destroyed Object: " << m_x << ")\n";
}
};
最初のメイン
std::list<Foo*> li;
li.push_back(Foo(1));
ここでは、一時的なFooオブジェクトを作成し、push_back()を呼び出します。一時オブジェクトがリストにコピーされ、関数が戻ります。このステートメントが完了すると、一時オブジェクトは(デストラクタを介して)破棄されます。リストが破棄されると、リストに含まれるすべてのオブジェクトも破棄されます(Fooはデストラクタを持つオブジェクトであるため、破棄にはデストラクタの呼び出しが含まれます)。
したがって、次のようなものが表示されるはずです。
Constructed Object: 1
Constructed Object: 101
DestroyedObject: 1
DestroyedObject: 101
2番目の例では、次のようになります。
std::list<Foo*> li;
li.push_back(new Foo(1));
ここでは、ヒープ上にオブジェクトを動的に作成します。次に、push_back()を呼び出します。ここでは、ポインターがリストにコピーされるため(ポインターにはコンストラクター/デストラクターがありません)、他に何も起こりません。これで、リストにヒープ上のオブジェクトへのポインターが含まれます。関数が返す場合、他には何も行われません。リストが破棄されると、リストに含まれるオブジェクト(ポインタ)が破棄されます(破棄と削除の微妙な違いに注意してください)が、ポインタにはデストラクタがないため、メモリリークは発生しません。
したがって、次のようなものが表示されるはずです。
Constructed Object: 1