1

次のことを行うと、メモリリークの問題が発生するのではないかと心配しています。

(サンプルコード)

class myItem //random container stuff mostly. All primatives.
{
    int index;
    char* name;
    int val1;
    int val2;
};

class vecList
{

    vector< myitem* > *myVec;

    void delete()
    { 
        MyVec->erase(std::remove_if(myVec->begin(), MyVec->end(), IsMarkedToDelete), MyVec->end()); //leak here?
    }
};

ポインターの場合、消去はメモリを解放しませんよね?remove_if を使用していなければ、ポインターを破棄する前に delete を呼び出すことができます。この場合、どうすればよいでしょうか?スマートポインター? それらをすべて再実装したくないし、boost ライブラリを追加したくありません。

ありがとう!

4

4 に答える 4

9

IsMarkedToDeletetrue が返されたら、関数内のアイテムを削除するだけです。

于 2011-11-01T14:49:04.983 に答える
3

オブジェクトへの唯一のポインタがベクトル内にある場合は、を呼び出すとすぐにメモリリークが発生しますremove_ifremove_if保持しているポインタを移動しますが、返すイテレータの背後にある値については何も言いません。したがって、[a, b, c, d]abなどが異なるポインタを表す)のようなものがある場合、その後e = remove_if( v.begin(), v.end(), matches(b) )、ベクトルは2番目[a, c, d, d]e 指しd、すべての痕跡がb永久に失われるようになります(おそらくそうなるでしょう)。

明らかな解決策は、で使用shared_ptrすることvectorです。これにより、最終的にから削除されたポインタが確実vector に削除されます。それができない場合は、2つのパスを使用できます。最初のパスは次のfor_eachようなものになります。

struct DeleteIfCondition
{
    void operator()( ObjectType* &ptr ) const
    {
        if ( condition( *ptr ) ) {
            ObjectType* tmp = ptr;
            ptr = NULL;
            delete tmp;
        }
    }
};

std::for_each( v.begin(), v.end(), DeleteIfCondition() );

機能オブジェクトとして、その後に:

v.erase( std::remove( v.begin(), v.end(), NULL ), v.end() );
于 2011-11-01T14:55:27.513 に答える
1

を使用してremove_iffor_each戻り値から最後まで削除してから消去できます。もちろん、それはあなたのコードを少し長くします。別の可能性はshared_ptr、コードがそれに同意する場合、ポインターを格納することです。

ベンジャミンが指摘したように、上記は率直な嘘であるため、「別の可能性」しか残されていません。

于 2011-11-01T14:35:40.117 に答える
0

この機能を使用できます:

template<typename T, typename TESTFN>
void delete_if(std::vector<T*>& vec, TESTFN&& predicate)
{
   auto it = remove_if(vec.begin(), vec.end(), [&](T* item) {
      if (predicate(item)) {
         delete item;
         return true;
      }
      return false;
   });
   vec.erase(it, vec.end());
}

元:

delete_if(MyVec, [](T* item) { return item->index == 5; });
于 2021-05-27T14:10:41.140 に答える