Как освободить указатель объекта в векторе? - PullRequest
4 голосов
/ 14 марта 2011

у меня есть;

class object {
                    // any private datas token in heap area 
             public : 
                   ~object () ; 

};

в функции;

 vector < object*> tmp ;

мой вопрос:

  • Как я могу стереть / освободить tmp[я] ?Другими словами, что я должен написать в object :: destructor?

Ответы [ 7 ]

17 голосов
/ 14 марта 2011

Вы, кажется, немного смущены.Здесь действуют две концепции:

  • Как мне, владельцу tmp, освободить объекты, на которые указывают указатели в пределах tmp?
  • Что следуетдеструктор для класса object (~object) do?

Это на самом деле не связано.Когда вы закончите работу с вектором tmp, вы должны вручную пройти и вызвать delete для каждого из его элементов, чтобы освободить память, занятую объектом object, на который указывает элемент.Это предполагает, что элементы были выделены с помощью new, конечно.

Цель деструктора object ~object - освободить все, что принадлежит объекту object, не чтобы освободить сам object объект.Если объект object не владеет никакими динамически распределенными данными, ему не нужно ничего делать.

Другими словами, когда вы пишете delete tmp[i], происходят две вещи:

  1. *(tmp[i])::~object() называется
  2. Память, на которую указывает tmp[i], освобождается

Обратите внимание, что (2) происходит, даже если (1) абсолютно ничего не делает.Суть шага (1) состоит в том, чтобы позволить объекту, который должен быть удален, освободить любой из его объектов-членов, которые должны быть освобождены.Задача деструктора состоит в том, чтобы не решительно освобождать объект, на который он был вызван.

В явном примере:

class object {
  private:
    int foo;
  public:
    object() : foo(42) {}
    ~object() { /* nothing to do here; foo is not dynamically allocated */ }
};

int main() {
  vector<object*> tmp;
  tmp.push_back(new object());

  // Do some stuff with tmp

  for (int i = 0; i < tmp.size(); ++i) {
    delete tmp[i]; // Calls ~object and deallocates *tmp[i]
  }
  tmp.clear();

  return 0;
}

Или, напротив,

class object {
  private:
    int* foo;
  public:
    object() : foo(new int()) { *foo = 42; }
    ~object() { 
      // Now since foo is dynamically allocated, the destructor
      // needs to deallocate it
      delete foo;
    }
};

int main() {
  vector<object*> tmp;
  tmp.push_back(new object());

  // Do some stuff with tmp

  for (int i = 0; i < tmp.size(); ++i) {
    delete tmp[i]; // Calls ~object (which deallocates tmp[i]->foo) 
                   // and deallocates *tmp[i]
  }
  tmp.clear();

  return 0;
}
3 голосов
/ 14 марта 2011

Я написал этот шаблон универсальной функции, который должен помочь вам:

template<typename FwdIterator>
void deleter(FwdIterator from, FwdIterator to)
{
   while ( from != to ) 
   {
       delete *from;
       from++;
   }
}

Пример:

struct object { ~object() { cout << "object deleted" << endl; } };

int main() {

        vector<object*> objects;
        objects.push_back(new object());
        objects.push_back(new object());
        objects.push_back(new object());
        objects.push_back(new object());
        objects.push_back(new object());

        deleter(objects.begin(), objects.end()); //delete objects
        objects.clear(); //clear the vector
        return 0;
}

Вывод:

object deleted
object deleted
object deleted
object deleted
object deleted

Демонстрация на ideone:http://www.ideone.com/t5PI0

1 голос
/ 14 марта 2011

Вы можете просто позвонить delete tmp[i];. Но я бы рекомендовал использовать std::vector< std::shared_ptr< object > > вместо.

0 голосов
/ 14 марта 2011

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

Что касается вектора, он содержит указатели, а не экземпляры объектов. Таким образом, вызов erase() удалит только указатели из вектора, но не освободит объекты, на которые указывают указатели. Вы должны освободить объекты отдельно, например:

std::vector<object*> tmp;
tmp.push_back(new object);
...
std::vector<object*>::iterator iter = ...;
delete *iter;
tmp.erase(iter);
0 голосов
/ 14 марта 2011

Чтобы удалить объект в конце этого указателя, вызовите delete myVector [i]

Чтобы затем удалить этот указатель из вектора, вызовите myVector.erase (myVector.begin () + i)

0 голосов
/ 14 марта 2011

Вы можете использовать vector :: erase ..

А ваш деструктор object должен delete всех членов, которые вы выделили в куче.

0 голосов
/ 14 марта 2011

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

Поскольку этот указатель объекта хранится внутри вектора, вы должны удалить ссылку на него после его уничтожения.То есть стереть этот объект * из вектора.

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