Важный
Пожалуйста, помните, что у std::auto_ptr
есть много недостатков, и обычно вместо этого следует использовать std::unique_ptr
, если ваш компилятор предоставляет его. (Если это не так, обновите свой компилятор! :))
Теперь вернемся к вашему вопросу...
Какой смысл использовать этот auto_ptr? Он вызывает деструктор класса, когда выходит за пределы области действия, поскольку обычная переменная инициализации класса (a)
Точно. Причина для auto_ptr
заключается в том, чтобы обеспечить строгую семантику владения, чтобы объект правильно уничтожался при уничтожении самого указателя.
Я не могу передать этот указатель функции с указателем класса (func)
Вы можете, вам нужно использовать get()
для поиска необработанного указателя. Использование get()
при передаче указателя на вызов функции означает, что функция не собирается брать на себя ответственность за объект (auto_ptr
по-прежнему владеет им и ожидает, что он будет по-прежнему действителен после возврата из функции).
В качестве альтернативы вы можете использовать release()
для указателя, чтобы получить необработанный указатель И указать, что auto_ptr
больше не несет ответственности за владение объектом.
Я не могу использовать указатель auto_ptr для A[] или char[], потому что auto_ptr вызывает delete, а не delete[]
Да, это проблема. Это одна из причин, почему больше не используют auto_ptr
с момента появления unique_ptr
. Он делает то же самое, но безопаснее (= проще) в использовании и более универсален.
Единственное, что я думаю, это то, что мне не нужно писать «удалить», но какой смысл в указателе, если он будет уничтожен, когда я выйду за пределы области видимости.
Чтобы вы его не забыли :-) Или вы можете использовать auto_ptr
(или лучше unique_ptr
как член в объекте класса).
а скажи мне, какой смысл использовать auto_ptr, а не обычный указатель?
Короче говоря: многие указатели могут указывать на один объект. Существуют всевозможные интеллектуальные указатели, использующие систему типов для учета того, какой указатель владеет объектом (= отвечает за его освобождение).
Дополнительное примечание
Если у вас есть класс, который (может) владеть экземпляром другого объекта, вы просто пишете:
class X {
// ...
X() : ptr(new Type()) {}
X(Type ptr) : ptr(ptr) {}
// ...
void setPtr(Type ptr2) { ptr.reset(ptr); }
// ...
std::unique_ptr<Type> ptr;
};
Если установлено ptr
, то, например, деструктор unique_ptr
позаботится об удалении объекта (если он есть). В методе setPtr
функция reset()
удалит старый экземпляр (если он есть) и установит элемент в новый предоставленный экземпляр (или нуль — это нормально).
Теперь сравните другую ситуацию:
class X {
// ...
X() : ptr(new Type()) {}
X(Type ptr) : ptr(ptr) {}
// ...
void setPtr(Type ptr2) {delete ptr; ptr = ptr2;}
// ...
Type* ptr;
};
Такое же поведение? Нет! Потому что теперь, чтобы иметь безопасный код C++, вам дополнительно нужно написать деструктор для удаления ptr
при уничтожении X
.
Хорошо сейчас? НЕТ! Потому что, поскольку у вас есть общий деструктор, вам нужно свернуть (или заблокировать) свой собственный конструктор копирования и оператор присваивания, потому что в противном случае вы можете получить два экземпляра X, указывающих на один и тот же объект Type, и оба экземпляра здесь будут думать, что они владеют этим экземпляром, и оба когда-нибудь попытаются его удалить. Бум, нарушение прав доступа.
Unique_ptr не позволит вам неявно скопировать объект X вместе со строгой ссылкой на ptr
, потому что unique_ptr не копируется (он считает, что это единственный unique_ptr для объекта, поэтому это единственный экземпляр интеллектуального указателя, ответственный за удаление это - но это нормально, если необработанные, не принадлежащие указатели указывают на него, если они не пытаются удалить то, что им не принадлежит!).
И это еще не все — unique_ptr не может быть скопирован, но у него есть готовый для вас конструктор перемещения и оператор присваивания перемещения! Следовательно, вы можете безопасно вернуть его из функций и так далее.
Вот как типобезопасность интеллектуальных указателей преобразуется в более безопасный код.
Золотое правило: старайтесь не писать «удалить» (если только вы не пишете свои собственные контейнеры или умные указатели). :)
person
Kos
schedule
23.10.2011