💡Задача: На языке C++ создайте собственную реализацию интеллектуального указателя с автоматическим управлением памятью.

💡Задача: На языке C++ создайте собственную реализацию интеллектуального указателя с автоматическим управлением памятью.

https://t.me/cpluspluc

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

Впервые это может показаться сложной задачей, особенно для тех, кто не является экспертом в языке C++.

Решение: 

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

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

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

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

SmartPointer(T * object) {
 /* Мы хотим установить значение T * obj и установить счетчик
  * ссылок в 1. */
}

SmartPointer(SmartPointer & sptr) {
 /* Этот конструктор создает новый интеллектуальный указатель на существующий
  * объект. Нам нужно сперва установить obj и ref_count
  * такими же, как в sptr. Затем, 
  * поскольку мы создали новую ссылку на obj, нам нужно
  * увеличить ref_count. */
}

~SmartPointer(SmartPointer sptr) {
 /* Уничтожаем ссылку на объект. Уменьшаем
  * ref_count. Если ref_count = 0, освобождаем память и
  * уничтожаем объект. */
}

Существует дополнительный способ создания ссылок — установка одного SmartPointer в другой. Нам понадобится переопределить оператор = для обработки этого случая, но сначала давайте сделаем набросок кода:

onSetEqals(SmartPointer ptr1, SmartPointer ptr2) {
 /* Если ptr1 имеет существующее значение, уменьшить его количество ссылок.
 * Затем копируем указатели obj и  ref_count. Наконец,
 * так как мы создали новую ссылку, нам нужно увеличить
 * ref_count. */
}

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

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;
}




Report Page