4

があるとしますstd::vector<Obj *> objs(パフォーマンス上の理由から、実際の s ではなくポインターがありますObj)。

obj.push_back(new Obj(...));繰り返し入力します。

終わったらdelete、押し戻された要素に取り掛かる必要があります。1つの方法はこれを行うことです:

for (std::vector<Obj *>::iterator it = objs.begin(); it != objs.end(); ++it) {
    delete *it;
}

for_eachただし、アルゴリズムを使用して同じことができるかどうかに興味があります。

#include <algorithm>
...
for_each(objs.begin(), objs.end(), delete);

どう思いますか?

4

7 に答える 7

16

あなたの問題は、それdeleteが関数ではなくキーワードであるため、そのアドレスを取得できないことです。

C++0x では、std::default_delete(によって使用される) クラスがありstd::unique_ptr、それを使用できます。または、誰もが言っているように、自分で作成するのは簡単です (標準のクラスでも、不完全なものを削除しようとすると、コンパイル エラーが発生します)。タイプ)。

#include <vector>
#include <algorithm>
#include <memory>

int main()
{
    std::vector<int*> vec;
    std::for_each(vec.begin(), vec.end(), std::default_delete<int>());
}
于 2010-08-17T17:54:36.303 に答える
10

はい。ただし、ファンクターが必要です。

struct delete_ptr
{
    template <typename T>
    void operator()(T* pPtr)
    {
        delete pPtr;
    }
};

std::for_each(objs.begin(), objs.end(), delete_ptr());

C++0x では、ラムダを使用してファンクターをインプレースで作成できます。

std::for_each(objs.begin(), objs.end(), [](Obj* pPtr){ delete pPtr; });

ただし、これは例外があるため危険です。sbi が解決策を示しました。

于 2010-08-17T17:50:55.627 に答える
4

これを行うことはできますが ( GMan が解決策を示しています)、所有するリソースへのネイキッド ポインターを含むコンテナーを使用することは、強いコード臭です。たとえば、次のコードで:

  void foo()
  {
    std::vector<Obj *> bar;
    fill(bar);
    use(bar);
    std::for_each(objs.begin(), objs.end(), delete_ptr()); // as GMan suggests
  }

スローするuse()と、オブジェクトがリークします。

したがって、これにはスマート ポインターを使用することをお勧めします。

std::vector< std::shared_ptr<Obj> > bar;
于 2010-08-17T17:55:41.920 に答える
2

削除の問題を解決しようとする代わりにshared_ptr、ベクトルにsを格納するか、ブーストを使用することで、完全に解消することができますptr_vectorhttp://www.boost.org/doc/libs/1_39_0/libs/ptr_container/docを参照)。 /tutorial.html)。

于 2010-08-17T18:07:58.303 に答える
2

ではない正確に; for_eachで呼び出すことができる関数またはオブジェクトが必要であり、関数()でもオブジェクトでdeleteもありません。おそらく次のように、関数(または関数オブジェクト)でラップする必要があります。

struct Deleter
{
    void operator()(Obj* obj) {delete obj;}
};

std::for_each(objs.begin(), objs.end(), Deleter());

ただし、生のポインターを使用してオブジェクトの有効期間を管理する場合は特に注意が必要です。特にそれらを渡している場合はそうです。から消去する場合vector、または再割り当てする場合、または をクリアするvector場合、または例外、ブレーク、または関数の戻りによってベクトルが破棄される可能性がある場合は、忘れずにそれらを削除する必要があります。一般に、リソース管理とリソース使用の責任を分離することは常に良いことです。

ポリモーフィックな基本クラスでない限り、オブジェクトのベクトルを使用したほうがよいでしょうObj。または、オブジェクトが実際に大きくまたは複雑であり、コピーするとパフォーマンスに顕著な影響が出る場合を除きます。その場合 (そして、その場合であることを確認するためにプロファイルを作成した場合)、スマート ポインターのベクトル ( shared_ptr、またはunique_ptrコンパイラがサポートしている場合)、または Boost のを検討する必要がありますptr_vector

自動リソース管理クラスを使用する習慣を身につければ、将来の頭痛の種を大幅に減らすことができます。

于 2010-08-17T18:04:21.073 に答える
1

はい。スマート ポインターで埋めて vector.clear() を使用するのが最も簡単な方法です。

于 2010-08-17T18:17:54.127 に答える
1

for_each関数ポインタまたは関数オブジェクトが必要です。&::operator deleteメモリの割り当て解除については、メモリの割り当てを解除する関数のアドレスを取得する を試すことができます。ただし、delete ステートメントを使用すると、コンパイラは呼び出す前にデストラクタを呼び出すoperator delete(void*)ため、クリーンアップは実際にはoperator delete(void*)関数の一部ではありません。

functor ala GMan's answer を使用します。

于 2010-08-17T17:56:50.103 に答える