4

ベクトルで動的に作成されたアイテムを手動で削除する必要があるのはなぜですか?ベクトルが削除されたときに、なぜそれらが削除されないか、そのデストラクタが呼び出されないのですか?

通常はこのようなものですが、なぜ必要なのですか?

vector<int*> v;
for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it) 
{ 
   delete *it; 
}
4

4 に答える 4

12

まず、生のポインタをベクターに格納します。これらのポインタは単なるポインタです。彼らはどこを指すことができます。ローカルオブジェクトを指すことができますが、。で削除することはできませんdelete。また、動的に作成されたオブジェクトを指している場合でも、必ずしもユーザーがそれらをベクターで死なせたいという意味ではありません。ベクトルはどのようにしてこれらすべてを知っているはずですか?

それはオブジェクトの所有権の問題です。オブジェクトを所有する人は誰でも、その適切でタイムリーな削除に責任があります。通常の生のポインタは所有権を表しません。そのため、vectorは、オブジェクトを削除する必要があるかどうかについて推測することはできません。ベクトルが動的オブジェクトを所有していることをベクトルに伝えたい場合は、対応するスマートポインターを使用します。

次に、一般的なケースでは、削除手法が必ずしも安全であるとは限らないことに注意してください。一部の標準コンテナは、格納するデータが常に有効であると想定しています。delete各ベクトル要素に対して実行すると、ベクトル内のデータは「無効」になります(ポインターは不確定になります)。これはベクトルでOKです。std::mapしかし、std::unordered_setたとえば、のような「よりスマートな」コンテナでこのようなことを行うと、問題が発生する可能性があります。直後にコンテナ自体を破棄したとしても、コンテナの破棄アルゴリズムが個々の要素の値を分析(比較、ハッシュなど)する必要がある可能性があります。そして、あなたはあなたのサイクルでそれらすべてを殺しました。

スマートポインタは自然にこの問題を解決します。ただし、標準のコンテナに格納されているrawポインタのマニュアルを使用する必要がある場合は、次deleteの手順を実行することをお勧めします。

  1. で要素の値を取得しi、ポインタに格納しますp
  2. iコンテナから要素を消去します
  3. 行うdelete p

最終的には、空のコンテナとdeletedデータになります。繰り返しになりますが、あなたのアプローチはやのような単純なシーケンスで機能しますが、順序付けられたシーケンスstd::vectorstd::listハッシュされたシーケンスではこれを行わないでください。

于 2012-08-05T00:58:21.293 に答える
6

なぜなら、言語には、終わったときに生き続ける必要があるかどうかを知る方法がないからです。スタックオブジェクトなどへのポインタを挿入した場合はどうなりますか?ブーム。

ただし、これは、自動破棄に関する適切なポリシー実装するスマートポインターを使用することで解決できます。unique_ptrそしてshared_ptr、最も一般的で便利です。

于 2012-08-05T00:49:49.327 に答える
3

ポインタが指すオブジェクトを所有していないため、デストラクタは呼び出されません。

C ++ 11では、astd::unique_ptr<T>は実際にそれが指すオブジェクトを所有しています。この場合、ポインタが解放されたときにデストラクタが呼び出されます。これはおそらく必要な動作です。(C ++ 11コンパイラーはないが、かなり最近のC ++ 11以前のコンパイラーがある場合unique_ptrは、TR1の一部として引き続き使用できます。)

于 2012-08-05T00:48:26.800 に答える
1

の実装は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;
    }
}
于 2012-08-05T00:35:53.737 に答える