Язык программирования C++ от Страуструпа


..Контейнеры и удаление - часть 2


template<class T> MVector {

  T* p;

  int sz;

  public:

     MVector(int s);

     ~MVector();

     // ...

};

template<class T> MVector<T>::MVector(int s)

{

  // проверка s

  p = new T[sz=s];

  for (int i = 0; i<s; i++) p[i] = 0;

}

 

template<class T> MVector<T>::~MVector()

{

  for (int i = 0; i<s; i++) delete p[i];

  delete p;

}

Пользователь может рассчитывать, что содержащиеся в MVector указатели будут удалены. Отсюда следует, что после удаления MVector пользователь не должен обращаться с помощью указателей к объектам, заносившимся в этот контейнер. В момент уничтожения MVector в нем не должно быть указателей на статические или автоматические объекты, например:

void h()

// корректное использование средств управления памятью

{

  MVector<Shape*> v(10);

  Circle* cp = new circle();

  v[0] = cp;

  v[1] = new Triangle;

  Square s;

  v[2] = &s;

  v[2] = 0;                        // предотвращает удаление s

                                   // все оставшиеся указатели

                                   // автоматически удаляются при выходе

}

Естественно, такое решение годится только для контейнеров, в которых не содержатся копии объектов, а для класса Map ($$8.8), например, оно не годится. Здесь приведен простой вариант деструктора для MVector, но содержится ошибка, поскольку один и тот же указатель, дважды занесенный в контейнер, будет удаляться тоже два раза.

Построение и уничтожение таких контейнеров, которые следят за удалением содержащихся в них объектах, довольно дорогостоящая операция. Копирование же этих контейнеров следует запретить или, по крайней мере, сильно ограничить (действительно, кто будет отвечать за удаление контейнер или его копия?):

template<class T> MVector {

  private:

     MVector(const MVector&);       //предотвращает копирование

     MVector& operator=(const MVector&); //то же самое

     // ...

};

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




- Начало -  - Назад -  - Вперед -