17

StackOverflowを検索しましたが、この質問に対する答えが見つかりませんでした。

std::vector<Day *> vector_dayオブジェクトへのポインタのベクトルである-を持っていると仮定しDayます。今私push_backvector_day多くの要素に:

vector_day.push_back(new Day(12));
vector_day.push_back(new Day(99));
vector_day.push_back(new Day(71));
...

今、ある時点で私はもう必要ありませんvector_day。メモリを解放する正しい方法は何ですか?

これは正しい方法です:

for (std::vector<Day *>::iterator i = vector_day.begin(); i != vector_day.end(); ++i) {
    delete *i;
}

これは、削除するたびにベクトルを無効にしませんか?私は非常に混乱しています。

4

10 に答える 10

18

どうしても必要がない場合は、そもそもポインタをベクトルに入れないのが最善の方法です。

しかし、本当にポインターのベクトルが必要な場合は、それを実行する方法は問題ありません(ただし.clear()、ベクトルのアフターワードは、すぐに破棄されないため、ダングリングポインターでいっぱいにはなりません)。

ステートメント

delete *it;

イテレータには影響しません。イテレータを変更したり、イテレータを無効にしたり、イテレータによって参照されているポインタをコレクションから削除したりすることはありません。イテレータが参照するポインタが指すメモリを解放するだけです。ポインタ自体は、コレクションから個別に削除する必要があります。

于 2010-07-27T15:07:46.510 に答える
7

ptr_vectorをブーストして救助しましょう!

std :: vectorの内容を繰り返して削除する必要なしに、必要なことを正確に実行します

于 2010-07-27T18:40:08.740 に答える
5

これを行う別のC++の方法は、ヘルパー構造体を定義することです。

struct delete_ptr { // Helper function to ease cleanup of container
    template <typename P>
    void operator () (P p) {
        delete p;
    }
};

次に、アルゴリズムを使用します。

std::for_each(vector_day.begin(), vector_day.end(), delete_ptr());
vector_day.clear();
于 2010-07-27T15:59:51.947 に答える
2

一般に、C ++では、メモリエラーを回避するために、メモリ管理を可能な限り非表示にする必要があります。ポインタのコピーをたくさん行っていて、パフォーマンスを気にしない限り、shared_ptrを使用します。

これはTR1標準の一部であり、ほとんどの最新のC ++コンパイラですぐに使用でき(http://anteru.net/2008/09/01/260/)、ファイアアンドフォーゲットメモリ管理に最適です。

于 2010-07-27T16:12:35.933 に答える
1

おそらく、ある種の管理対象ポインター、おそらく共有ポインターを使用する必要があります。

他の誰かがそれらのポインタの1つを保持している間にベクトルを削除すると、それらが間接参照しようとすると、非常に厄介な動作が発生します。共有ポインタはあなたにその頭痛を救うでしょう。

ベクトルが削除された後、他に何もポインターを参照しないことを保証できる場合でも、自動ポインターを使用することでメリットが得られます。ベクトルが破壊されたときに、割り当て解除を管理します。オーバーヘッドは最小限であり、それはあなたの人生をはるかに楽にします。

于 2010-07-27T15:18:04.093 に答える
0

配列に要素を追加または削除する操作は、イテレータを無効にする可能性があります。さまざまなコンテナタイプの特定のルールについては、ドキュメントを確認してください。を使用deleteすると、配列の形状ではなく、配列要素に含まれるデータを操作できます。イテレータはコンテナの形状をトラバースします。コンテナの内容は気にしません。

于 2010-07-27T15:07:53.593 に答える
0

まず、からiに切り替えましたがit、これは単なるタイプミスだと思います。

しかし、あなたの探求に答えるために、いいえ、それは問題ありません。あなたは変わっていませんit、あなたは変わってい*itます。

于 2010-07-27T15:09:00.493 に答える
0

大丈夫です。*i(ベクトルの要素)ではなく(ベクトルの要素が指すオブジェクト)を削除iしているので、ベクトルは無効になりません。

開発者がすべてのを削除したい場合、およびループ後の解決策( )については、この質問を参照してください。ivector_day.clear()

于 2010-07-27T15:50:43.250 に答える
0

これは、同じ問題を扱っているときに私が少し前に書いた便利なクラスです。いくつかのコードを古いRogueWaveベースのベクターとリストからSTLベースのベクターとリストに変換していて、ポインターリスト用のRWのclearAndDestroy()メソッドをエミュレートする方法が必要でした。clearAndDestroy()メソッドは、さまざまな構造タイプを処理するためにオーバーライドできます(簡潔にするためにここにベクトルのみを含めました)。

class StlUtils
{
   public:

      /**
       * This method provides a templated way to destroy a std::vector
       * full of pointers.  It is basically a replacement for the RW
       * vector class' clearAndDestroy methods.  The list argument is
       * returned empty.
       *
       * @param list the list of pointers to be destroyed.
       */
      template<class T> static void clearAndDestroy(
         std::vector<T*> &itemList)
      {
         for_each(itemList.begin(), itemList.end(),
                  stl_deleter<T>());
         itemList.clear();
      }

   private:

      /**
       * Templated member function for use with the clearAndDestroy()
       * method.  It provides the method needed by for_each to do the
       * actual deletion.
       */
      template<class T> struct stl_deleter
      {
         void operator() (T* x) {
            if (x != NULL)
               delete x;
         }
      };
};
于 2010-07-27T21:42:59.697 に答える
0

反復+削除のもう1つの方法は、while(!empty)ループを使用することです。この手法の利点は、要素が最初にコンテナから削除され、その後に削除されることです。これはどのコンテナでも安全です。

while (!vector_day.empty()) {
    Day* day = vector_day.back();
    vector_day.pop_back();
    delete day;
}
于 2018-07-02T06:51:21.013 に答える