Skip to content

Latest commit

 

History

History
104 lines (83 loc) · 4.68 KB

ptr.md

File metadata and controls

104 lines (83 loc) · 4.68 KB

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

Storage duration – это свойство объекта, которое описывает, когда тот попадает в память и когда её освобождает. В C++ их 4 вида:

  • автоматическая storage duration (на основании scope)
  • статическая (static, extern)
  • storage duration потока
  • динамическая (new/delete)

Проблемы:

  • утечка памяти (не вызывается delete)
  • сложность разделения указателей не владеющие объектом (owning pointer) и использующие объект (non owning pointer)
  • при использовании простых указателей (raw pointer) сложно без комментариев определить какой тип указателя (owning/non owning pointer)

Где должен вызываться delete?

int* func();

std::unique_ptr

Класс, который ссылается на объект в динамической памяти и при выходе из области видимости уничтожает хранимый объект.

{
    std::unique_ptr<X> prt(new X());
} // здесь указатель уничтожается, перед этим память под X освобождается

std::make_unique

Проблемы:

  • нужно писать имя класса дважды:
  • есть проблема неопределенного порядка вычисления аргументов
void func(std::unique_ptr<A> a,std::unique_ptr<B> b){};
int main(){
    func(std::unique_ptr<A>(new A()), std::unique_ptr<B>(new B()));
}

Возможен следующий порядок вычисления аргументов:

new A() 
new B()
std::unique_prt<A>( ... )
std::unique_prt<B>( ... )

std::make_unique решает эти проблемы

auto prt = std::make_unique<X>();

Особенности:

  • std::unique_ptr - объект должен иметь только одного владельца
  • право на владение можно передать std::move()
void func(std::unique_prt<X> a){}
int main(){
    auto a = std::make_unique<X>();
    func(a); // не скомпилируется
    func(std::move(a)); // владение передано в func, при выходе из func объект будет освобожден
}
  • std::unique_ptr нельзя копировать
  • объект для использования можно передавать по raw pointer
void func(X* a){}
int main(){
    auto a = std::make_unique<X>();
    finc(a.get());
}

std::shared_ptr

std::shared_ptr - класс, который ссылается на объект в динамической памяти, у которого может быть несколько владельцев, и при уничтожении всех владельцев класс уничтожает хранимый объект.

{
    auto prt = std::make_shared<X>();
    {
        auto ptr2 = ptr;
    }
}

std::weak_ptr

std::weak_ptr - это фактически умный указатель non owning, предназначенный для использования именно с std::shared_ptr

Особенности:

  • Копирование std::weak_ptr не увеличивает счётчик в std::shared_ptr, а значит и не защищает объект от уничтожения
  • всегда имеется возможность проверить, существует ли ещё объект, на который ссылается std::weak_ptr, или нет

Вообще говоря, std::weak_ptr необходимо использовать всегда, когда надо ссылаться на управляемый std::shared_ptr объект, но не защищать его от уничтожения.

std::auto_ptr

Не использовать. Этот умный указатель был помечен как устаревший в C++ 11, а в C++ 17 был полностью удалён из стандарта языка

Причины:

  • std::auto_ptr реализовывает семантику перемещения через конструктор копирования и оператор присваивания. Объект удаляется при передачи в функцию по значению
  • std::auto_ptr всегда удаляет свое содержимое, используя оператор delete, который не работает с массивами