Как удалить элементы в векторе, если с помощью remove_if и items являются указателями на объекты? - PullRequest
1 голос
/ 01 ноября 2011

Боюсь, что я сталкиваюсь с проблемами утечки памяти, выполняя следующие действия:

(Пример кода)

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 для указателя, прежде чем уничтожить его.Как бы я это сделал в этом случае?Умные Указатели?Я бы предпочел не переустанавливать все вместе с ними, и я действительно не хочу добавлять библиотеку наддува.

Спасибо!

Ответы [ 3 ]

8 голосов
/ 01 ноября 2011

Вы можете просто удалить элемент в функции IsMarkedToDelete, когда он вернет true.

3 голосов
/ 01 ноября 2011

Если только указатели на объект были в векторе, то вы утечка памяти, как только вы позвоните remove_if. remove_if перемещает указатели, которые вы удерживаете, но это ничего не говорит о значения за итератором, который он возвращает. Таким образом, если у вас есть что-то как [a, b, c, d] (где a, b и т. д. представляют разные указатели), затем после e = remove_if( v.begin(), v.end(), matches(b) ) ваш вектор может (и, вероятно, будет) выглядеть как [a, c, d, d], с e указывая на второй d, и все следы b потеряны навсегда.

Очевидным решением будет использование shared_ptr в vector; этот будет гарантировать, что любой указатель, который в конечном итоге был удален из vector будет удален В противном случае вы можете использовать два прохода: первый будет быть 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() );
1 голос
/ 01 ноября 2011

Вы можете использовать remove_if, затем for_each от возвращаемого значения до конца, а затем стереть. Это, конечно, сделает ваш код немного длиннее. Другая возможность - хранить shared_ptr указатели, если ваш код согласен с этим.

Вышесказанное - грубая ложь, как указывал Бенджамин, поэтому у вас остается только "другая возможность".

...