Почему автоматический ptr устарел?
Я слышал auto_ptr
устарел в C++11. В чем причина этого?
также я хотел бы знать разницу между auto_ptr
и shared_ptr
.
5 ответов
прямая замена для auto_ptr
(или самое близкое к одному в любом случае) - это unique_ptr
. Что касается "проблемы", это довольно просто: auto_ptr
передает право собственности, когда оно назначено. unique_ptr
также передает право собственности, но благодаря кодификации семантики перемещения и магии ссылок rvalue это может сделать значительно более естественно. Он также" подходит " к остальной части стандартной библиотеки значительно лучше (хотя, справедливости ради, некоторые из них благодаря остальной части библиотеки, изменяющейся для размещения семантики перемещения, а не всегда требующей копирования).
изменение имени также (IMO) приветствуется -auto_ptr
на самом деле не говорит вам много о том, что он пытается автоматизировать, тогда как unique_ptr
является довольно разумным (если кратким) описанием того, что предоставляется.
Я нашел существующие ответы отличными,но из PoV указателей. IMO, идеальный ответ должен иметь перспективный ответ пользователя / программиста.
первым делом (как указал Джерри Коффин в своем ответе)
- auto_ptr может быть заменен shared_ptr или unique_ptr в зависимости от ситуации
shared_ptr: если вы обеспокоены освобождением ресурса / памяти и если у вас есть более одной функции, которая может использовать объект в разное время, а затем перейти к shared_ptr.
в разное время подумайте о ситуации, когда объект-ptr хранится в нескольких структурах данных и позже доступен. Еще один пример-несколько потоков.
unique_ptr является : если все, что вас интересует, - это освобождение памяти, а доступ к объекту последовательный, перейдите к unique_ptr.
последовательным, я имею в виду, в любой момент объект будет доступен из одного контекст. Е. Г. объект, который был создан, и сразу после создания творцом. После создания объект сохраняется в первый структура данных. Затем либо объект уничтожается после одной структуры данных, либо перемещается в второй структура данных.
из этой строки я буду ссылаться на shared / unique _ptr как смарт-указатели. (auto_ptr также является смарт-указателем, но из-за недостатков в его дизайне,для которого они устарели, и который я думаю, я укажу в следующих строках, они не должны быть сгруппированы с помощью smart-pointer. )
самая важная причина, по которой auto_ptr был устаревшим в пользу smart-pointer назначение-семантика если бы не эта причина, они бы добавили все новые лакомства семантики перемещения в auto_ptr вместо того, чтобы осуждать его. Поскольку назначение-семантика была самой нелюбимой функцией, они хотели, чтобы эта функция ушла, но так как есть код, написанный, который использует эту семантику (какие стандарты-комитет не может изменить), они должны были отпустить auto_ptr, вместо того, чтобы изменять его.
по ссылке:http://www.cplusplus.com/reference/memory/unique_ptr/operator=/
вид заданий, поддерживаемых unqiue_ptr
- переместить задание (1)
- присвоить значение null указатель (2)
- тип-cast назначение (3)
- копировать назначение (удалено!) (4)
From:http://www.cplusplus.com/reference/memory/auto_ptr/operator=/
вид заданий, поддерживаемых auto_ptr
- копировать назначение (4) виновником
сейчас почему присвоение себе копию так нелюбит, у меня есть теория :
- не все программисты читают книги или стандарты
- auto_ptr на первый взгляд, обещает вам право собственности на объект
- маленькое-* (каламбур), предложение auto_ptr, которое не читается всеми программистами, позволяет присваивать один auto_ptr другому и передает право собственности.
- исследования показали, что это поведение предназначено для 3.1415926535 % всего использования, и непредусмотренные в других случаях.
непреднамеренное поведение действительно не нравится и, следовательно, нелюбовь к в auto_ptr.
(для 3.1415926536% программистов, которые намеренно хотят передать владение C++11, дали им std:: move(), что сделало их намерение кристально ясным для всех стажеров, которые собираются читать и поддерживать код.)
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
установлен nullptr
, и проблема в том, что это может произойти слишком легко, без того, чтобы программист продумал свою безопасность.
class
/struct
есть std::auto_ptr
член, затем создание копии экземпляра будет release
указатель из копируемого экземпляра: это странная и опасно запутанная семантика, поскольку обычно копирование чего-то не изменяет его. Автору класса / структуры легко пропустить выпуск указатель при рассуждении об инвариантах и состоянии и, следовательно, случайной попытке разыменования смарт-указателя в то время как null, или просто еще не ожидали доступа/владения указанными данными.auto_ptr нельзя использовать в контейнерах STL, потому что он имеет конструктор копирования, который не соответствует требованиям container 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