ベクトルで動的に作成されたアイテムを手動で削除する必要があるのはなぜですか?ベクトルが削除されたときに、なぜそれらが削除されないか、そのデストラクタが呼び出されないのですか?
通常はこのようなものですが、なぜ必要なのですか?
vector<int*> v;
for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it)
{
delete *it;
}
ベクトルで動的に作成されたアイテムを手動で削除する必要があるのはなぜですか?ベクトルが削除されたときに、なぜそれらが削除されないか、そのデストラクタが呼び出されないのですか?
通常はこのようなものですが、なぜ必要なのですか?
vector<int*> v;
for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it)
{
delete *it;
}
まず、生のポインタをベクターに格納します。これらのポインタは単なるポインタです。彼らはどこを指すことができます。ローカルオブジェクトを指すことができますが、。で削除することはできませんdelete
。また、動的に作成されたオブジェクトを指している場合でも、必ずしもユーザーがそれらをベクターで死なせたいという意味ではありません。ベクトルはどのようにしてこれらすべてを知っているはずですか?
それはオブジェクトの所有権の問題です。オブジェクトを所有する人は誰でも、その適切でタイムリーな削除に責任があります。通常の生のポインタは所有権を表しません。そのため、vectorは、オブジェクトを削除する必要があるかどうかについて推測することはできません。ベクトルが動的オブジェクトを所有していることをベクトルに伝えたい場合は、対応するスマートポインターを使用します。
次に、一般的なケースでは、削除手法が必ずしも安全であるとは限らないことに注意してください。一部の標準コンテナは、格納するデータが常に有効であると想定しています。delete
各ベクトル要素に対して実行すると、ベクトル内のデータは「無効」になります(ポインターは不確定になります)。これはベクトルでOKです。std::map
しかし、std::unordered_set
たとえば、のような「よりスマートな」コンテナでこのようなことを行うと、問題が発生する可能性があります。直後にコンテナ自体を破棄したとしても、コンテナの破棄アルゴリズムが個々の要素の値を分析(比較、ハッシュなど)する必要がある可能性があります。そして、あなたはあなたのサイクルでそれらすべてを殺しました。
スマートポインタは自然にこの問題を解決します。ただし、標準のコンテナに格納されているrawポインタのマニュアルを使用する必要がある場合は、次delete
の手順を実行することをお勧めします。
i
、ポインタに格納しますp
i
コンテナから要素を消去しますdelete p
最終的には、空のコンテナとdelete
dデータになります。繰り返しになりますが、あなたのアプローチはやのような単純なシーケンスで機能しますが、順序付けられたシーケンスstd::vector
やstd::list
ハッシュされたシーケンスではこれを行わないでください。
なぜなら、言語には、終わったときに生き続ける必要があるかどうかを知る方法がないからです。スタックオブジェクトなどへのポインタを挿入した場合はどうなりますか?ブーム。
ただし、これは、自動破棄に関する適切なポリシーを実装するスマートポインターを使用することで解決できます。unique_ptr
そしてshared_ptr
、最も一般的で便利です。
ポインタが指すオブジェクトを所有していないため、デストラクタは呼び出されません。
C ++ 11では、astd::unique_ptr<T>
は実際にそれが指すオブジェクトを所有しています。この場合、ポインタが解放されたときにデストラクタが呼び出されます。これはおそらく必要な動作です。(C ++ 11コンパイラーはないが、かなり最近のC ++ 11以前のコンパイラーがある場合unique_ptr
は、TR1の一部として引き続き使用できます。)
の実装はvector
、そのメモリのみを削除するために作成されました。ポインタにはデコンストラクタはありません。また、C ++では、ガベージコレクションや、それがポインターであることを確認して再帰的に削除するロジックはありません。
次のISO会議に出席して、それを提案したい場合は、私のゲストになりますが、私にとっては、それをinline
関数に入れます。
template<class T>
public static inline void deleteVectorPointer(std::vector<T*> v)
{
for (vector<T*>::iterator i = v.begin(); i != v.end(); i++)
{
delete *i;
}
}