|
Программирование >> Операторы преобразования типа
public; Инициализация объекта существующим указателем - указатель р должен быть лолучен в результате вызова new explicit CountedPtr СТ* р=0) : ptrCp). count(new long(l)) { Копирующий указатель Сувеличиеает счетчик владельцев) CountedPtr (const CountedPtr<T>& р) throwO : ptr(p.ptr). count(p.count) { ++*count; Деструктор (уничтожает объект, если владелец был последним -CountedPtr О throwO { disposeO: Присваивание (перевод указателя на новый объект) CountedPtr<T>& operator= (const CountedPtr<T>& p) throwC) { if (this != &p) { disposeO: ptr = p.ptr: count = p.count: ++*count: return *this: Доступ к объекту, на который ссылается указатель Т& operator*0 const throwO { return *ptr: T* operdtor->() const throwO { return ptr: private: void disposeO { if (--*count == 0) { delete count; delete ptr: #endif /COUNTED PTR HPP*/ Класс напоминает стандартный класс умного указателя auto ptr (см. с. 54). Предполагается, что значения, которыми инициализируются умные указатели, были возвращены оператором new. В отличие от класса auto ptr это позволяет копировать умные указатели так, чтобы оригинал и копия оставались действительными. Объект уничтожается только после удаления последнего указателя, ссылающегося на него. lOiacc CounterPtr можно усовершенствовать, например реализовать в нем автоматическое преобразование типов или возможность передачи права владения от умного указателя вызывающей стороне. Ниже приведен пример использования класса CountedPtr: cont/refseml.cpp #1nclude <lostream> #include <l1st> finclude <deque> Iinclude <algorithm> #include countptr.hpp using namespace std: void printCountedPtr (CountedPtr<1nt> elem) { cout *elem ; 1nt mainO ( Массив целых чисел (для совместного использования в разных контейнерах) static int values[] = { 3. 5, 9. 1, 6. 4 }: Две разные коллекции typedef CountedPtr<int> IntPtr: deque<IntPtr> colli; list<IntPtr> С0112: Вставка общих объектов в коллекции * - исходный порядок в coin * - обратный порядок в col 12 for (int i=0; i<sizeof(values)/sizeof(values[0]); ++i) { IntPtr ptr(new int(values[i])); colli.push back(ptr): coll2.push front(ptr); Вывод содержимого обеих колпекций for each (col 11 .beginC), colli,endO. printCountedPtr): cout endl: Рекомендации по выбору контейнера 229 for each Ссо112,beginO. coll2.endO. printCountedPtr): cout endl endl: /* Модификация значений в разных коллекциях * - возведение в квадрат третьего значения в colli * - изменение знака первого значения е colli * - обнуление первого значения в со112 */ *со111[2] *= *colU[2]: (**со111.beginO) -1: (**со112.beginO) = 0: Повторный вывод содержимого обеих коллекций for each (colU.beginO. colli.endO. printCountedPtr): cout endl; for each (coll2.beginO. coll2.end(). printCountedPtr): cout endl: Результат выполнения программы выглядит так: 3 5 9 16 4 4 6 1 9 5 3 -3 5 81 1 6 О О 6 1 81 5 -3 Если вызвать вспомогательную функцию, сохраняющую элемент коллекции (IntPtr) где-то в другом месте, то значение, на которое ссылается указатель, остается действительным даже после уничтожения коллекций или удаления из них всех элементов. В архиве Boost библиотек С++ (http: www.boost.org/) хранятся различные классы умных указателей, расширяющие стандартную библиотеку С++ (вероятно, вместо CounterPtro стоит поискать название shared ptr<>). Рекомендации по выбору контейнера Стандартная библиотека С++ содержит разные типы контейнеров, обладающие разными возможностями. Возникает вопрос: когда использовать тот или иной тип контейнера? В табл. 6.33 приводятся некоторые рекомендации. Однако эти общие утверждения не всегда согласуются с реальностью. Например, при малом количестве элементов фактор сложности можно не учитывать, потому что обработка малого количества элементов с линейной сложностью происходит быстрее, чем обработка большого количества элементов с логарифмической сложностью.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |