Вы находитесь на странице: 1из 3

Умный указатель на C++

Умный (интеллектуальный) указатель — это тот же обычный указатель, обеспечивающий


безопасность благодаря автоматическому управлению памятью. Такой указатель помогает
избежать множества проблем: «висячие» указатели, «утечки» памяти и отказы в выделении
памяти. Интеллектуальный указатель должен подсчитывать количество ссылок на указанный
объект.

На первый взгляд эта задача кажется довольно сложной, особенно если вы не эксперт в C++.
Один из полезных подходов к решению — разделить задачу на две части: 1) обрисовать
общий подход и создать псевдокод, а затем 2) написать подробный код.

Нам нужна переменная — счетчик ссылок, которая будет увеличиваться, как только мы
добавляем новую ссылку на объект, и уменьшаться, когда мы ее удаляем. Наш псевдокод
может иметь следующий вид:

1 template
2 class SmartPointer {
3 /* Класс интеллектуального указателя нуждается в указателях на собственно
4 * себя и на счетчик ссылок. Оба они должны быть указателями, а не реальным
5 * объектом или значением счетчика ссылок, так как цель интеллектуального
6 * указателя - в подсчете количества ссылок через множество интеллектуальных
7 * указателей н один объект */
8 T * obj;
9 unsigned * ref_count;
10 }

Для этого класса нам потребуется конструктор и деструктор, поэтому опишем их:

1 SmartPointer(T * object) {
2 /* Мы хотим установить значение T * obj и установить счетчик
3 * ссылок в 1. */
4 }
5
6 SmartPointer(SmartPointer & sptr) {
7 /* Этот конструктор создает новый интеллектуальный указатель на существующий
8 * объект. Нам нужно сперва установить obj и ref_count
9 * такими же, как в sptr. Затем,
10 * поскольку мы создали новую ссылку на obj, нам нужно
11 * увеличить ref_count. */
12 }
13
14 ~SmartPointer(SmartPointer sptr) {
15 /* Уничтожаем ссылку на объект. Уменьшаем
16 * ref_count. Если ref_count = 0, освобождаем память и
17 * уничтожаем объект. */
18 }

Существует дополнительный способ создания ссылок — установка одного SmartPointer в


другой. Нам понадобится переопределить оператор = для обработки этого случая, но сначала
давайте сделаем набросок кода:
1 onSetEqals(SmartPointer ptr1, SmartPointer ptr2) {
2 /* Если ptr1 имеет существующее значение, уменьшить его количество ссылок.
3 * Затем копируем указатели obj и ref_count. Наконец,
4 * так как мы создали новую ссылку, нам нужно увеличить
5 * ref_count. */
6}

Осталось только написать код, а это дело техники:

1 template
2 class SmartPointer {
3 public:
4 SmartPointer(T * ptr) {
5 ref = ptr;
6 ref_count = (unsigned*)malloc(sizeof(unsigned));
7 *ref_count = 1;
8 }
9
10 SmartPointer(SmartPointer & sptr) {
11 ref = sptr.ref;
12 ref_count = sptr.ref_count;
13 ++(*ref_count);
14 }
15
16 /* Перезаписываем оператор равенства (eqal), поэтому когда вы установите
17 * один интеллектуальный указатель в другой, количество ссылок старого указателя
18 * будет уменьшено, а нового - увеличено.
19 */
20 SmartPointer & operator=(SmartPointer & sptr) {
21 /* Если уже присвоено объекту, удаляем одну ссылку. */
22 if (*ref_count > 0) {
23 remove();
24 }
25 if (this != &sptr) {
26 ref = sptr.ref;
27 ref_count = sptr.ref_count;
28 ++(*ref_count);
29 }
30 return *this;
31 }
32
33 ~SmartPointer() {
34 remove(); // удаляем одну ссылку на объект.
35 }
36
37 T operator*() {
38 return *ref;
39 }
40
41 protected:
42 void remove() {
43 --(*ref_count);
44 if (ref_count == 0) {
45 delete ref;
46 free(ref_count);
47 ref = NULL;
48 ref_count = NULL;
49 }
50 }
51
52 T * ref;
53 unsigned * ref_count;
54

Вам также может понравиться