Уничтожает ли vector :: erase () вектор указателей объекта сам объект? - PullRequest
39 голосов
/ 15 июня 2011

У меня есть вектор указателей на объекты. Мне нужно удалить элемент из вектора и поместить этот элемент в другой список.

Я читал, что стирание может использоваться для удаления объекта из вектора, но я также читал, что он вызывает деструктор объектов, прежде чем сделать это.

Мне нужно знать, уничтожит ли объект также его.

Ответы [ 5 ]

59 голосов
/ 15 июня 2011

vector::erase
Удаляет из векторного контейнера и вызывает его деструктор, но если содержащийся объект является указателем, он не становится владельцем его уничтожения.

Вам придется явно вызывать delete для каждого содержащегося в нем указателя, чтобы удалить содержимое, на которое он указывает, например:

void clearVectorContents( std::vector <YourClass*> & a ) 
{    
    for ( int i = 0; i < a.size(); i++ ) 
    {       
        delete a[i];    
    }    
    a.clear(); 
} 

Хранение необработанных указателей в стандартных контейнерах не является хорошей идеей.Если вам действительно нужно хранить ресурсы, которые должны быть выделены на new, тогда вы должны использовать boost::shared_ptr.Ознакомьтесь с документацией Boost .

Более общее и элегантное решение:
В этом решении используется for_each & templates, как @Billy указал в комментариях:

// Functor for deleting pointers in vector.
template<class T> class DeleteVector
{
    public:
    // Overloaded () operator.
    // This will be called by for_each() function.
    bool operator()(T x) const
    {
        // Delete pointer.
        delete x;
        return true;
    }
};

И это можно назвать так:

for_each( myclassVector.begin(),myclassVector.end(),
          DeleteVector<myclass*>());

, где myclassVector - ваш вектор, содержащий указатели на класс myclassобъекты.

Пример использования:

#include "functional"
#include "vector"
#include "algorithm"
#include "iostream"

//Your class
class myclass
{
    public:
        int i;
        myclass():i(10){}
};


// Functor for deleting pointers in vector.
template<class T> class DeleteVector
{
    public:
    // Overloaded () operator.
    // This will be called by for_each() function.
    bool operator()(T x) const
    {
        // Delete pointer.
        delete x;
        return true;
    }
};


int main()
{
    // Add 10 objects to the vector.
    std::vector<myclass*> myclassVector;

    for( int Index = 0; Index < 10; ++Index )
    {
        myclassVector.push_back( new myclass);
    }

    for (int i=0; i<myclassVector.size(); i++) 
    {
        std::cout << " " << (myclassVector[i])->i;
    }

    // Now delete the vector contents in a single  line.
    for_each( myclassVector.begin(),
              myclassVector.end(),
              DeleteVector<myclass*>());

    //Clear the vector 
    myclassVector.clear();

    std::cout<<"\n"<<myclassVector.size();

    return 0;
}
9 голосов
/ 21 сентября 2012
  • Если у вас vector<MyObject>, будет вызван MyObject::~MyObject.
  • Если у вас vector<MyObject*>, то delete <MyObject instance> не будет вызван.

Чтобы переместить MyObject между двумя векторами, вам нужно сначала вставить его в вектор назначения, а затем стереть оригинал.Обратите внимание, что это создаст новую копию объекта.При перемещении указателей вы можете просто сохранить указатель во временной переменной, стереть его из вектора, а затем вставить туда, где вам нужно.

А вот еще один простой способ удалить, а затем удалить все элементы в векторе:

template<class T> void purge( std::vector<T> & v ) {
    for ( auto item : v ) delete item;
    v.clear();
}
2 голосов
/ 15 июня 2011

Да, erase уничтожает элемент. Однако, если вы помещаете элемент в другой контейнер, вы, вероятно, сделали копию, поместив его в этот другой контейнер. Единственный способ столкнуться с проблемами - скопировать указатель или что-то подобное в другой контейнер.

2 голосов
/ 15 июня 2011

Да. vector::erase уничтожает удаленный объект, что включает вызов его деструктора.

2 голосов
/ 15 июня 2011

Да, конечно, будет.Если объект не существует в векторе, где еще он будет существовать?

Редактировать: не удалит все, на что указывает указатель.Вы должны использовать автоматические указатели времени жизни, такие как shared_ptr для управления временем жизни объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...