Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Gosy_nepolnostyu_7v1.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
3.7 Mб
Скачать

Умные указатели

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

Класс auto_ptr

Класс auto_ptr из библиотеки STL имеет следующие ограничения:

  • объектом может владеть только один указатель,

  • объектом не может быть массив,

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

Единственное предназначение этого класса автоматизировать уничтожение выделенной ранее памяти. Таким образом, данный класс используется, когда время существование выделенного объекта можно ограничить определенным блоком. Аналогичными свойствами обладает и класс scoped_ptr из библиотеки Boost. Но в отличие от auto_ptr для этого класса запрещена передача объекта от одного указателя к другому. Делая код более безопасным, данные классы не наносят ущерб размеру или скорости программы.

#include <memory> // здесь объявление шаблона класса auto_ptr #include <iostream> using namespace std; // Внутри функции мы выделяем память для объекта типа int // но не освобождаем ее явно оператором delete. // Это делается автоматически при выходе из функции, // когда уничтожаются все локальные переменные. void func() { auto_ptr<int> aptr(new int(20)); auto_ptr<int> aptr2; cout<<"*aptr="<<*aptr<<endl; // следующая строка была бы невозможна при использовании scope_ptr aptr2=aptr; // теперь aptr не владеет никаким объектом         cout<<"*aptr2="<<*aptr2<<endl; }

Класс shared_ptr

Класс shared_ptr из Boost обладает расширенными возможностями:

  • объект может иметь несколько владельцев;

  • можно указать дополнительный класс, отвечающий за уничтожение объекта.

#include <boost/shared_ptr.hpp> #include <iostream> using namespace boost; using namespace std; class A { shared_ptr<int> ptr; public: A(shared_ptr<int> pptr) : ptr(pptr) {} void setValue(int n) {*ptr=n;} }; class B { shared_ptr<int> ptr; public: B(shared_ptr<int> pptr) : ptr(pptr) {} int getValue() const {return *ptr; } }; int main() { shared_ptr<int> ptr(new int(45)); A a(ptr); B b(ptr); cout<<"b.getValue()="<<b.getValue()<<endl;   a.setValue(50); cout<<"now b.getValue()="<<b.getValue()<<endl;        }

New/delete и классы

Оператор new можно перегрузить для новых классов, а оператор delete для классов автоматически вызывает деструктор.

Пример: http://habrahabr.ru/post/148657/

Операторы new и delete можно перегрузить. Для этого есть несколько причин:

  • Можно увеличить производительность за счёт кеширования: при удалении объекта не освобождать память, а сохранять указатели на свободные блоки, используя их для вновь конструируемых объектов.

  • Можно выделять память сразу под несколько объектов.

  • Можно вести лог выделения/освобождения памяти.

Операторы new и delete имеют следующие сигнатуры:

void *operator new(size_t size); void operator delete(void *p);

Оператор new принимает размер памяти, которую необходимо выделить, и возвращает указатель на выделенную память.

class A { public:    void *operator new(size_t size);    void operator delete(void *p); }; void *A::operator new(size_t size) {    printf("Allocated %d bytes\n", size);    return malloc(size); } void A::operator delete(void *p) {    free(p); }

Вместо функций malloc и free можно использовать глобальные операторы ::new и ::delete.

Рекомендуется не производить в операторе new (особенно в глобальном) какие-либо операции с объектами, которые могут вызвать оператор new. Например, для вывода текста используется функция printf, а не объект std::cout.

Операторы new и delete, объявленные внутри класса, функционируют подобно статическим функциям и вызываются для данного класса и его наследников, для которых эти операторы не переопределены.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]