Умные указатели(Smart pointers)

Smart pointer — это объект, работать с которым можно как с обычным указателем, но при этом, в отличии от последнего, он предоставляет дополнительные функции (например, автоматическое освобождение закрепленной за указателем области памяти). Умные указатели призваны для борьбы с утечками памяти, которые сложно избежать в больших проектах. 

В старом стандарте существует умный указатель auto_ptr:  

Пример использования этого указателя:       

   #include <memory>
  using namespace std;
int main()
{ string*p = new string("abc"); auto_ptr <string> smart_pointer(p); auto_ptr <string> new_smart_pointer; new_smart_pointer = smart_pointer; cout << *new_smart_pointer << endl; 

p = new_smart_pointer.get();
smart_pointer =(auto_ptr <string> )p; //явное преобразование типа данных cout << *smart_pointer << endl;

smart_pointer -> insert(smart_pointer -> begin(), 'f'); cout << *smart_pointer << endl; return 0; }

std::auto_ptr помечен как deprecated в новом стандарте, а это значит вы должны прекратить его использовать, если использовали когда-либо.

Суть проблемы auto_ptr описывается так: для этого типа разрешено копирование, которое несет в себе серьезный побочный side effect. Если вы 
разрешаете для какого-то типа копирование, то это копирование должно всегда порождать абсолютно эквивалентную копию. Потому что 
копирование может произойти случайно (забыли & добавить) или не совсем явным образом (как для поля в составе другого типа, для которого 
копирование разрешено). 
В новом стандарте языка у типов, наравне с понятием copyable/non-copyable, появилось новое свойство - movable/non-movable. Т.е. тип можно быть не копируемым, но при этом поддерживать move семантику. Теперь действительно можно безопасно применить разрушающее копирование (пример - вернуть такой указатель из функции).

В новом стандарте появился указатель unique_ptr:

Пример использования этого указателя:
#include <memory>
using namespace std;

struct Foo{                                                   
    Foo() { cout << "Foo::Foo\n"; }          
    ~Foo() { cout << "Foo::~Foo\n"; }       
    void bar() { cout << "Foo::bar\n"; }    
};                                                                   
void f(const Foo &foo) 
{ cout << "f(const Foo&)\n";  }
 
int main()
{
    unique_ptr<Foo> p1(new Foo); 

    if (p1) p1->bar();
    {
        unique_ptr<Foo> p2(move(p1));  
        f(*p2);   //
        p1 = move(p2);  
        cout << "Destroying p2...\n";
    }
 // экземпляр Foo уничтожен, когда p1 покидает область видимости
 
    return 0;
}


Comments