Я слышал auto_ptr
, что C ++ 11 устарел. Что является причиной этого?
Также хотелось бы узнать разницу между auto_ptr
и shared_ptr
.
c++
c++11
smart-pointers
auto-ptr
бретт
источник
источник
Ответы:
Прямая замена
auto_ptr
(или, по крайней мере, самая близкая к ней) естьunique_ptr
. Что касается «проблемы», все довольно просто:auto_ptr
передает право владения, когда оно назначено.unique_ptr
также передает право собственности, но благодаря кодификации семантики перемещения и магии ссылок rvalue это может происходить значительно более естественно. Он также значительно лучше «вписывается» в остальную часть стандартной библиотеки (хотя, честно говоря, отчасти это произошло благодаря тому, что остальная часть библиотеки изменилась с учетом семантики перемещения, а не всегда требовала копирования).Изменение имени также (ИМО) приветствуется - на
auto_ptr
самом деле мало что говорит вам о том, что оно пытается автоматизировать, тогдаunique_ptr
как это довольно разумное (если краткое) описание того, что предоставляется.источник
auto_ptr
название: auto предлагает автоматический, как в автоматической переменной, и относится к одной вещи, котораяauto_ptr
делает: уничтожает управляемый ресурс в его деструкторе (когда он выходит за пределы области видимости).auto_ptr
: open-std.org/jtc1/sc22/wg21/docs/papers/2005/…std::sort
не имеет специализацииunique_ptr
. Вместо этого было изменено указание никогда не копировать. Так наauto_ptr
самом деле делает работу с современнымsort
. Но C ++ 98/03sort
является здесь просто примером алгоритма: любой общий алгоритм (предоставленный стандартным или написанным пользователем), который предполагает, что синтаксис копирования имеет семантику копирования, вероятно, будет иметь ошибку времени выполнения, если используется сauto_ptr
, потому что перемещаетсяauto_ptr
незаметно с копией синтаксиса. Проблема гораздо шире, чем просто .sort
Я нашел существующие ответы отличными, но из PoV указателей. ИМО, идеальный ответ должен иметь ответ с точки зрения пользователя / программиста.
Первым делом (как указал Джерри Коффин в своем ответе)
shared_ptr: если вас беспокоит освобождение ресурса / памяти И если у вас есть несколько функций, которые могут использовать объект AT-DIFFERENT раз, тогда используйте shared_ptr.
В DIFFERENT-Times представьте себе ситуацию, когда объект-ptr хранится в нескольких структурах данных, а затем к нему осуществляется доступ. Другой пример - это, конечно, несколько потоков.
unique_ptr: если все, что вас беспокоит, - это освобождение памяти, а доступ к объекту - ПОСЛЕДОВАТЕЛЬНЫЙ, выберите unique_ptr.
Под ПОСЛЕДОВАТЕЛЬНОМ я подразумеваю, что в любой момент объект будет доступен из одного контекста. Например, объект, который был создан и использовался сразу после создания создателем. После создания объект сохраняется в ПЕРВОЙ структуре данных. Затем объект либо уничтожается после ОДНОЙ структуры данных, либо перемещается во ВТОРОЙ структуру данных.
В этой строке я буду называть общий / уникальный _ptr интеллектуальными указателями. (auto_ptr также является умным указателем, НО из-за недостатков в его конструкции, из-за которых они устарели и на которые, я думаю, я укажу в следующих строках, их не следует группировать с помощью умного указателя.)
По ссылке: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/
Вид присваиваний, поддерживаемых unqiue_ptr
От: http://www.cplusplus.com/reference/memory/auto_ptr/operator=/
Вид присваиваний, поддерживаемых auto_ptr
Теперь, когда я перехожу к причине, ПОЧЕМУ само назначение копий так не понравилось, у меня есть следующая теория:
Непредвиденное поведение действительно не нравится и, следовательно, неприязнь к auto_ptr.
(Для 3,1415926536% программистов, которые намеренно хотят передать право собственности, C ++ 11 дал им std :: move (), что сделало их намерение совершенно ясным для всех стажеров, которые собираются читать и поддерживать код.)
источник
auto_ptr
значения указывали на один и тот же объект (поскольку они не предоставляют совместного владения, первое, что умрет, оставит другое со смертельным наследием; это также верно дляunique_ptr
использования), можете ли вы предложить, что было предназначено в оставшиеся 96,8584073465% всего использования?*a=*b;
здесь только значение b копируется в a. Я надеюсь, что и a, и b по-прежнему принадлежат одним и тем же людям. Вы упомянули, что собственность будет передана. Как это будет?auto_ptr
объекту. Присвоение / от указанной стоимости не влияет на право собственности и не имеет отношения к ней. Надеюсь, вы еще не пользуетесьauto_ptr
?shared_ptr
можно хранить в контейнерах.auto_ptr
не могу.Кстати,
unique_ptr
это действительно прямаяauto_ptr
замена, она сочетает в себе лучшие черты обоихstd::auto_ptr
иboost::scoped_ptr
.источник
Еще один подход к объяснению разницы ....
Функционально C ++ 11
std::unique_ptr
является «фиксированным»std::auto_ptr
: оба они подходят, когда - в любой момент времени во время выполнения - должен быть один владелец смарт-указателя для объекта, на который указывает.Ключевое различие заключается в создании копирования или присваивании из другого умного указателя с истекшим сроком действия, что показано в
=>
строках ниже:std::auto_ptr<T> ap(...); std::auto_ptr<T> ap2(get_ap_to_T()); // take expiring ownership => std::auto_ptr<T> ap3(ap); // take un-expiring ownership ala ap3(ap.release()); ap->xyz; // oops... can still try to use ap, expecting it to be non-NULL std::unique_ptr<T> up(...); std::unique_ptr<T> up2(get_up_to_T()); // take expiring ownership => std::unique_ptr<T> up3(up); // COMPILE ERROR: can't take un-expiring ownership => std::unique_ptr<T> up4(std::move(up)); // EXPLICIT code allowed => std::unique_ptr<T> up4(up.release()); // EXPLICIT code allowed
Выше он
ap3
незаметно «крадет» право собственности*ap
, оставляяap
набор на anullptr
, и проблема в том, что это может произойти слишком легко, если программист не продумал его безопасность.Например, если у
class
/struct
естьstd::auto_ptr
член, то при создании копии экземпляра будетrelease
указатель из копируемого экземпляра: это странная и опасно запутывающая семантика, поскольку обычно копирование чего-либо не меняет его. Автору класса / структуры легко не заметить освобождение указателя, рассуждая об инвариантах и состоянии, и, следовательно, случайно попытаться разыменовать интеллектуальный указатель, пока он равен нулю, или просто еще не ожидает доступа / владения указанными данными.источник
auto_ptr нельзя использовать в контейнерах STL, потому что у него есть конструктор копирования, который не соответствует требованиям контейнера CopyConstructible . unique_ptr не реализует конструктор копирования, поэтому контейнеры используют альтернативные методы. unique_ptr может использоваться в контейнерах и быстрее для алгоритмов std, чем shared_ptr.
#include <iostream> #include <type_traits> #include <vector> #include <memory> using namespace std; int main() { cout << boolalpha; cout << "is_copy_constructible:" << endl; cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl; cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl; cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl; vector<int> i_v; i_v.push_back(1); cout << "i_v=" << i_v[0] << endl; vector<int> i_v2=i_v; cout << "i_v2=" << i_v2[0] << endl; vector< unique_ptr<int> > u_v; u_v.push_back(unique_ptr<int>(new int(2))); cout << "u_v=" << *u_v[0] << endl; //vector< unique_ptr<int> > u_v2=u_v; //will not compile, need is_copy_constructible == true vector< unique_ptr<int> > u_v2 =std::move(u_v); // but can be moved cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl; vector< shared_ptr<int> > s_v; shared_ptr<int> s(new int(3)); s_v.push_back(s); cout << "s_v=" << *s_v[0] << endl; vector< shared_ptr<int> > s_v2=s_v; cout << "s_v2=" << *s_v2[0] << endl; vector< auto_ptr<int> > a_v; //USAGE ERROR return 0; } >cxx test1.cpp -o test1 test1.cpp: In function âint main()â: test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations] vector< auto_ptr<int> > a_v; //USAGE ERROR ^ >./test1 is_copy_constructible: auto_ptr: false unique_ptr: false shared_ptr: true i_v=1 i_v2=1 u_v=2 s_v=3 s_v2=3
источник