Шаблон для очистки от вектора уничтожения - как? - PullRequest
1 голос
/ 31 мая 2009

Я пытаюсь реализовать шаблон, который позволил бы создать класс, производный от вектора <>, чтобы при удалении удалялся элемент вектора. Приведенный ниже фрагмент кода представляет собой попытку сделать это:

include <vector>

using namespace std;

template <class P>
class TidyVector : public vector<P> {
 public:
  ~TidyVector() {
    while (vector<P>::size()) {
      P pi = vector<P>::back();
      vector<P>::pop_back();
      delete pi;
    }
  }
}

TidyVector<int*> i;

Попытки скомпилировать это с помощью g ++ -c try.cc приводят к следующим сообщениям об ошибках:

try.cc:1: error: expected constructor, destructor, or type conversion before '<' token
try.cc:6: error: expected template-name before '<' token
try.cc:6: error: expected `{' before '<' token
try.cc:6: error: expected unqualified-id before '<' token
try.cc:17: error: aggregate 'TidyVector<int*> i' has incomplete type and cannot be defined

Что происходит - почему это не работает? Или, может быть, уместнее задать вопрос: каков стандартный способ решения этой проблемы (автоматическая очистка вектора при удалении)?

Ответы [ 3 ]

4 голосов
/ 31 мая 2009

Уже существует класс, который делает это: Boost's ptr_vector . Я предлагаю проверить это и посмотреть, как они это сделали. Краткий ответ: они не используют наследование, они используют композицию.

4 голосов
/ 31 мая 2009

Я предполагаю, что это должно быть #include . Так что это одна ошибка.

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

(о, и вы оставили точку с запятой вне класса)

В-третьих, не задумывались ли вы о том, чтобы вместо этого использовать вектор >?

Разъяснение, почему подход shared_ptr лучше: ваш класс сейчас очищает вещи только в одном случае; если они все еще там, когда класс разрушен. Но скажем, у вас есть фид TidyVector с 10 элементами, а затем кто-то делает:

foo[5] = new int; // Memory leak!

Или

foo.resize(0); // Memory leak!

Или

foo.erase(foo.begin()); // Memory leak!

Список можно продолжить

1 голос
/ 31 мая 2009

Прочтите сообщения об ошибках компилятора: для начала вам не хватает символа # в #include.

В вашем деструкторе вам не нужно указывать vector<P>:: - вы производите от вектора, поэтому вызывайте его методы без квалификации, например, размер () и т. д.

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

for (iterator i = begin(); i != end; ++i)
    delete *i;

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

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

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