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