|
Программирование >> Разработка устойчивых систем
Освобождение контейнеров указателей в программе Stlshape.cpp уничтожение контейнера не приводило к автоматическому освобождению указателей. Конечно, нам хотелось бы упростить эту процедуру, чтобы ее не приходилось каждый раз программировать заново. Следующая шаблонная функция освобождает указатели в любом последовательном контейнере. Учтите, что в архиве примеров она находится в корневом каталоге (для упрощения доступа): : :purge.h Освобождение указателей в последовательных контейнерах STLcontainer #ifndef PURGE H #define PURGE H #include <a1gorithm> tempiate<c1ass Seq> void purge(Seq& c) { typename Seq:iterator i: ford = C.beginO: i != c.endO: ++i) { delete *i: *i = 0: Версия с итераторами: tempiate<class Inplt> void purgednpit begin. Inpit end) { whileCbegin != end) { delete *begin: *begin = 0: ++begi n: #endif PURGEJ /:- В первой версии purge() ключевое слово typename абсолютно необходимо. Перед нами та самая ситуация, для которой предназначалось это ключевое слово: Seq - аргумент щаблона, а iterator - нечто вложенное в этот щаблон. Что же тогда должна обозначать запись Seq::iterator? Ключевое слово typename указывает, что она обозначает тип и ничего больше. Хотя первая версия purge() ориентирована на контейнеры в стиле STL, вторая версия (с итераторами) работает с любыми интервалами, в том числе с массивами. Далее приведен новый вариант Stlshape.cpp с использованием функции purge(): : C07:Stlshape2.cpp Stlshape.cpp с использованием функции purgeO linclude <iostream> linclude <vector> linclude ../purge.h using namespace std: class Shape { public: virtual void drawO = 0: virtual -ShapeO {}: class Circle : public Shape { public: void drawO { cout Circle: :draw\n : } -CircleO { cout ~Circle\n : } class Triangle : public Shape { public: void drawO { cout Triangle: :draw\n : } -TriangleO { cout -TriangleNn : } class Square : public Shape { public: void drawO { cout Square: :draw\n : } -SquareO { cout -Square\n : } int mainO { typedef std::vector<Shape*> Container: typedef Container::iterator Iter: Container shapes: shapes.push back(new Circle): shapes.push back(new Square): shapes.push back(new Triangle): fordter i = shapes.beginO: i != shapes.endO: i++) (*i)->draw(): purge(shapes): } /:- При использовании функции purge() необходимо тщательно следить за принадлежностью объектов. Если указатель на объект хранится в двух контейнерах, нужно позаботиться о том, чтобы он не был освобожден дважды; кроме того, нельзя уничтожать объект из первого контейнера до того, как второй контейнер закончит работу с ним. С повторным освобождением указателей в одном контейнере проблем не будет, потому что purge() обнуляет указатель после его освобождения, а вызов delete для нулевого указателя является безопасной операцией. Создание пользовательских контейнеров Взяв STL за основу, вы можете создавать собственные контейнеры. Если вы соблюдаете все требования по поддержке итераторов, то новый контейнер будет работать так же, как стандартные контейнеры STL. Для примера возьмем кольцевую структуру данных, то есть циклический последовательный контейнер. При достижении последнего элемента перебор просто возвращается к началу. Реализация кольца на базе списка может выглядеть так: : С07:Ring.срр Построение кольцевой структуры данных на базе STL #i nclude <iostream> #i nclude <iterator> linclude <list> linclude <string> using namespace std: tempiate<class T> class Ring { list<T> 1st: public: Объявление класса необходимо для того, чтобы следующее объявление friend видело итератор iterator вместо std::iterator: class iterator: friend class iterator: class iterator : public std::iterator< std::bidirectional iterator tag.T.ptrdiff t>{ typename list<T>::iterator it: list<T>* r: public: iterator(list<T>& 1st. const typename list<T>::iterators i) : r(&lst). it(i) {} bool operator-=(const iterators x) const { return it == x.it: bool operator!-(const iterators x) const { return !(*this - x): typename 1i st<T>::reference operator*() const { return *it: iterators operator++() { ++it: if(it - r->end()) it - r->begin(): return *this: iterator operator++(int) { iterator tmp - *this: ++*this: return tmp: iterators operator--() { if(it = r->begin()) it = r->end(): --it: return *this: iterator operator--(int) { iterator tmp = *this: --*this: return tmp: iterator insert(const TS x){ return iterator(*r. r->insert(it. x)): iterator eraseO { return iterator(*r. r->erase(it)): void push back(const TS x) { lst.push back(x): } iterator beginO { return iteratordst. 1st.beginO): } int SizeO { return Ist.sizeO: } int mainO { Ring<string> rs:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |