1 added
1 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Теги: c++, программирование на c++, умный указатель, интеллектуальный указатель, smart pointer</p>
1
<p>Теги: c++, программирование на c++, умный указатель, интеллектуальный указатель, smart pointer</p>
2
<p><strong>Умный указатель в C++</strong>(его ещё называют интеллектуальным) обеспечивает безопасность за счёт автоматического управления памятью. Такое решение позволит избежать ряда проблем при написании кода (отказов в выделении памяти, "утечек" памяти и пр.)</p>
2
<p><strong>Умный указатель в C++</strong>(его ещё называют интеллектуальным) обеспечивает безопасность за счёт автоматического управления памятью. Такое решение позволит избежать ряда проблем при написании кода (отказов в выделении памяти, "утечек" памяти и пр.)</p>
3
<p>Умный указатель (<strong>Smart pointer</strong>) должен подсчитывать число ссылок на указанный объект. Поначалу может показаться, что это довольно сложная задача, особенно если вы не являетесь экспертом в C++. Давайте попробуем решить её, разделив на 2 части: 1) обрисуем общий подход и создадим псевдокод; 2) напишем подробный код.</p>
3
<p>Умный указатель (<strong>Smart pointer</strong>) должен подсчитывать число ссылок на указанный объект. Поначалу может показаться, что это довольно сложная задача, особенно если вы не являетесь экспертом в C++. Давайте попробуем решить её, разделив на 2 части: 1) обрисуем общий подход и создадим псевдокод; 2) напишем подробный код.</p>
4
<p>Нам потребуется переменная -<strong>счётчик ссылок</strong>. Переменная будет увеличиваться, если мы будем добавлять новую ссылку на объект, и уменьшаться, если будем удалять ссылку.</p>
4
<p>Нам потребуется переменная -<strong>счётчик ссылок</strong>. Переменная будет увеличиваться, если мы будем добавлять новую ссылку на объект, и уменьшаться, если будем удалять ссылку.</p>
5
<p><strong>Пример псевдокода</strong>:</p>
5
<p><strong>Пример псевдокода</strong>:</p>
6
template class SmartPointer { /* Класс Smart-указателя нуждается в указателях на самого * себя и на счётчик ссылок. Оба они должны быть указателями, а не реальным * объектом или значением счётчика ссылок, ведь цель умного * указателя - подсчитать число ссылок через множество * Smart-указателей на один объект */ T * obj; unsigned * ref_count; }<p>Для данного класса нам потребуются<strong>деструктор и конструктор</strong>, давайте опишем их:</p>
6
template class SmartPointer { /* Класс Smart-указателя нуждается в указателях на самого * себя и на счётчик ссылок. Оба они должны быть указателями, а не реальным * объектом или значением счётчика ссылок, ведь цель умного * указателя - подсчитать число ссылок через множество * Smart-указателей на один объект */ T * obj; unsigned * ref_count; }<p>Для данного класса нам потребуются<strong>деструктор и конструктор</strong>, давайте опишем их:</p>
7
SmartPointer(T * object) { /* Мы желаем установить значение T * obj и установить счетчик * ссылок в 1. */ } SmartPointer(SmartPointer & sptr) { /* Данный конструктор создает новый умный указатель на существующий * объект. Нам нужно сначала установить obj и ref_count * такими же, как в sptr. Потом, * т. к. мы создали новую ссылку на obj, нужно * увеличить ref_count. */ } ~SmartPointer(SmartPointer sptr) { /* Уничтожаем ссылку на объект. Уменьшаем * ref_count. Если ref_count = 0, то освобождаем память и * уничтожаем объект. */ }<p>Есть и дополнительный способ создания ссылок -<strong>установить один SmartPointer в другой</strong>. Для этого потребуется переопределить оператор, но давайте сначала сделаем набросок кода:</p>
7
SmartPointer(T * object) { /* Мы желаем установить значение T * obj и установить счетчик * ссылок в 1. */ } SmartPointer(SmartPointer & sptr) { /* Данный конструктор создает новый умный указатель на существующий * объект. Нам нужно сначала установить obj и ref_count * такими же, как в sptr. Потом, * т. к. мы создали новую ссылку на obj, нужно * увеличить ref_count. */ } ~SmartPointer(SmartPointer sptr) { /* Уничтожаем ссылку на объект. Уменьшаем * ref_count. Если ref_count = 0, то освобождаем память и * уничтожаем объект. */ }<p>Есть и дополнительный способ создания ссылок -<strong>установить один SmartPointer в другой</strong>. Для этого потребуется переопределить оператор, но давайте сначала сделаем набросок кода:</p>
8
-
onSetEqals(SmartPointer ptr1, SmartPointer ptr2) { /* Если ptr1 имеет существующее значение, уменьшаем его число ссылок. * Потом копируем указатели obj и ref_count. В результате, * поскольку мы создали новую ссылку, нужно увеличить * ref_count. */ }<p>Что же, теперь осталось лишь написать<strong>итоговый код</strong>:</p>
8
+
onSetEqals(SmartPointer ptr1, SmartPointer ptr2) { /* Если ptr1 имеет существующее значение, уменьшаем его число ссылок. * Потом копируем указатели obj и ref_count. В результате, * поскольку мы создали новую ссылку, нужно ув��личить * ref_count. */ }<p>Что же, теперь осталось лишь написать<strong>итоговый код</strong>:</p>
9
template class SmartPointer { public: SmartPointer(T * ptr) { ref = ptr; ref_count = (unsigned*)malloc(sizeof(unsigned)); *ref_count = 1; } SmartPointer(SmartPointer & sptr) { ref = sptr.ref; ref_count = sptr.ref_count; ++(*ref_count); } /* Перезаписываем оператор равенства (eqal), поэтому, когда вы установите * один умный указатель в другой, число ссылок старого указателя * уменьшится, а нового - увеличится. */ SmartPointer & operator=(SmartPointer & sptr) { /* Если уже присвоено объекту, удаляем одну ссылку. */ if (*ref_count > 0) { remove(); } if (this != &sptr) { ref = sptr.ref; ref_count = sptr.ref_count; ++(*ref_count); } return *this; } ~SmartPointer() { remove(); // удаляем одну ссылку на объект. } T operator*() { return *ref; } protected: void remove() { --(*ref_count); if (ref_count == 0) { delete ref; free(ref_count); ref = NULL; ref_count = NULL; } } T * ref; unsigned * ref_count; }<p>Вот и всё, ждём ваших комментариев!</p>
9
template class SmartPointer { public: SmartPointer(T * ptr) { ref = ptr; ref_count = (unsigned*)malloc(sizeof(unsigned)); *ref_count = 1; } SmartPointer(SmartPointer & sptr) { ref = sptr.ref; ref_count = sptr.ref_count; ++(*ref_count); } /* Перезаписываем оператор равенства (eqal), поэтому, когда вы установите * один умный указатель в другой, число ссылок старого указателя * уменьшится, а нового - увеличится. */ SmartPointer & operator=(SmartPointer & sptr) { /* Если уже присвоено объекту, удаляем одну ссылку. */ if (*ref_count > 0) { remove(); } if (this != &sptr) { ref = sptr.ref; ref_count = sptr.ref_count; ++(*ref_count); } return *this; } ~SmartPointer() { remove(); // удаляем одну ссылку на объект. } T operator*() { return *ref; } protected: void remove() { --(*ref_count); if (ref_count == 0) { delete ref; free(ref_count); ref = NULL; ref_count = NULL; } } T * ref; unsigned * ref_count; }<p>Вот и всё, ждём ваших комментариев!</p>
10
<p><em>Статья написана на основе одного из заданий книги "<strong>Карьера программиста. Как устроиться на работу в Google, Microsoft или другую ведущую IT-компанию</strong>", Лакман Г.</em></p>
10
<p><em>Статья написана на основе одного из заданий книги "<strong>Карьера программиста. Как устроиться на работу в Google, Microsoft или другую ведущую IT-компанию</strong>", Лакман Г.</em></p>
11
11