こんにちは、ヒープ変数に関連する疑いはほとんどありません...
以下のような関数を書きたい ->
struct test
{
int x;
int y;
};
test* fun()
{
test *ptr = new test;
return ptr;
}
私の疑問は、ヒープ変数がスコープ外になると、その値が失われることです。
間違いなくメモリリークです。(ヒープ変数が削除されていないため)
では、どうすればそのような機能を設計できますか。
こんにちは、ヒープ変数に関連する疑いはほとんどありません...
以下のような関数を書きたい ->
struct test
{
int x;
int y;
};
test* fun()
{
test *ptr = new test;
return ptr;
}
私の疑問は、ヒープ変数がスコープ外になると、その値が失われることです。
間違いなくメモリリークです。(ヒープ変数が削除されていないため)
では、どうすればそのような機能を設計できますか。
動的に割り当てられたオブジェクト (ヒープ変数と呼ばれるもの) は、それらが作成されたスコープの最後で破棄されません。それが動的割り当ての要点です。test
オブジェクトは動的に割り当てられますが、ポインターはptr
そうではありません。スコープ外になると破棄されます。でも大丈夫!関数からポインターの値をコピーすると、このコピーは引き続きtest
オブジェクトを指します。test
オブジェクトはまだそこにあります。あなたが書いた関数は問題ありませんが、スタイルが良くありません。
はい、あなたが作成したオブジェクトdelete
へのポインターを誰も操作しないと、メモリ リークが発生します。test
これは、このような生のポインターを返す場合の問題です。delete
作成しているオブジェクトの呼び出し元を信頼する必要があります。
void caller()
{
test* p = fun();
// Caller must remember to do this:
delete p;
}
これを行う一般的な C スタイルの方法 (C++ では絶対に推奨されません) は、 関数create_test
とdestroy_test
のペアを使用することです。これは依然として呼び出し元に同じ責任を負わせます:
void caller()
{
test* p = create_test();
// Caller must remember to do this:
destroy_test(p);
}
これを回避する最善の方法は、動的割り当てを使用しないことです。スタック上にオブジェクトを作成しtest
、関数の外にコピー (または移動) するだけです。
test fun()
{
test t;
return t;
}
動的割り当てが必要な場合は、スマート ポインターを使用する必要があります。具体的には、unique_ptr
タイプはここで必要なものです。
std::unique_ptr<test> fun()
{
return std::unique_ptr<test>(new test());
}
呼び出し元の関数は、それunique_ptr
を行うことを心配することなく、 を処理できdelete
ます。が範囲外になると、作成したオブジェクトunique_ptr
が自動的に削除されます。ただし、他の関数にオブジェクトを持たせたい場合、呼び出し元はそれを別の場所に渡すことができます。delete
test
ヒープ変数を返すのではなく、ヒープへのポインターを保持するスタック変数の値を返します。スタック変数がスコープ外になります。ポインターが指すメモリーはヒープ内にあり、範囲外になることはありません。
呼び出し元でメモリを解放しないと、メモリ リークが発生します。
私の疑問は、ヒープ変数がスコープ外になると、その値が失われることです。
ポインターを値で返すので、心配はいりません。そのため、ポインターはスコープ外になりますが、それが指すメモリを返すため、メモリ リークはありません (呼び出し元に依存して削除できる場合のみ)。
ただし、参照によってポインターを返すと、問題が発生します。
test*& fun() // note the & (reference)
{
test *ptr = new test;
return ptr;
}
ここでは、一時への参照を返しています。変数がスコープ外になると、存在しないオブジェクトを使用することになります。これが、参照によって一時を返すことができない理由です。