Удаление пользовательских векторов - C ++ - PullRequest
1 голос
/ 25 июня 2010

У меня есть 2 класса, скажем, A & B. В классе B есть собственный деструктор.В классе A у меня есть вектор указателей на объекты класса B. Вектор выглядит следующим образом:

vector<B*> vect;

В деструкторе для класса A как получить память?Если я перебираю вектор, получу ли я каждый объект и использую delete для каждого полученного объекта?Я пробовал это в деструкторе, но он не работает.

Любая помощь в решении этой проблемы приветствуется.Извините, но я не могу опубликовать код.

Ответы [ 6 ]

4 голосов
/ 25 июня 2010

Если А владеет вещами, на которые указывает vect, то он должен иметь возможность delete каждого элемента в пределах vect.Если при этом происходит сбой, у вас есть ошибка где-то в вашем коде.

В общем, вам лучше использовать умные указатели.Boost's ptr_vector (часть Boost.Pointer Container разработан для вашего конкретного примера, но простой std::vector<std::tr1::shared_ptr<B> > также будет работать (хотя и с большими накладными расходами и более неудобным синтаксисом).

1 голос
/ 25 июня 2010

В некоторых других сообщениях отмечалось, что вам лучше использовать умные указатели вместо указателей.Если вам по какой-либо причине необходимо использовать указатель, сначала вы должны удалить их в цикле.

for ( std::vector<B*>::iterator it = vect.begin(); it != vect.end(); ++it)
    delete (*it);
vect.clear();

edit: если ваша программа вызывает ошибку в деструкторе, значит, ваш код неверен.Возможно, вы помещаете элемент стека по адресу в векторе, но чтобы удалить объект, он должен быть в куче.

#include <iostream>
#include <vector>
#include <string>

class data {
public:
    std::string d;
    data(std::string _d) : d(_d) { }
};

class container {
public:
    std::vector<data*> c;
    container() { c.clear(); }
    void add (data *d) { c.push_back(d); }
    ~container() {
        for (std::vector<data*>::iterator it = c.begin(); it != c.end(); ++it)
            delete (*it); 
        c.clear();
    }
};

int main (int argc, char* argv[]) {

    typedef std::vector<std::string> sVec;
    typedef sVec::iterator sVecIter;

    std::vector<std::string> cmd (argv+1, argv+argc);

    {
    container k;            
    for (sVecIter it = cmd.begin(); it != cmd.end(); ++it)
        k.add(new data((*it)));

    }

    return 0;

}

Это работает без проблем.

1 голос
/ 25 июня 2010

Да, если элементы типа B* указывают на объекты, выделенные в куче, то для каждого элемента вы должны вызывать delete на нем.

0 голосов
/ 25 июня 2010

Вы хотите избежать хранения указателей в контейнерах, когда вам нужно управлять их временем жизни.

Если это единственный истинный владелец и гарантированно будет последним для очистки, тогда я бы пошел с

std::vector<B> vect;

Если у вас есть разные ссылки и время жизни, которые могут перекрываться, то shared_ptr будет лучше (std :: tr1 или boost в зависимости от компилятора)

std::vector< boost::shared_ptr<B> > vect;
0 голосов
/ 25 июня 2010

По вашему описанию кажется, что ваш член vect класса A должен обладать пожизненным владением данными, указанными B *.

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

vector< std::tr1::shared_ptr<B> > vect;

РЕДАКТИРОВАТЬ: заменил auto_ptr на std :: tr1 :: shared_ptr

0 голосов
/ 25 июня 2010

Да, вы бы зациклили вектор и удалили каждый элемент.Проблема в том, что вы забыли оператора полотенца на линии 42.

...