Конструктор unique_ptr<T>
принимает необработанный указатель на объект типа T
(поэтому он принимает a T*
).
В первом примере:
unique_ptr<int> uptr (new int(3));
Указатель является результатом new
выражения, а во втором примере:
unique_ptr<double> uptr2 (pd);
Указатель сохраняется в pd
переменной.
Концептуально ничего не меняется (вы создаете a unique_ptr
из необработанного указателя), но второй подход потенциально более опасен, поскольку он позволяет вам, например, делать:
unique_ptr<double> uptr2 (pd);
unique_ptr<double> uptr3 (pd);
Таким образом, имеется два уникальных указателя, которые эффективно инкапсулируют один и тот же объект (тем самым нарушая семантику уникального указателя).
Вот почему первая форма для создания уникального указателя лучше, когда это возможно. Обратите внимание, что в C ++ 14 мы сможем:
unique_ptr<int> p = make_unique<int>(42);
Что и понятнее, и безопаснее. Теперь по поводу вашего сомнения:
Мне также непонятно, чем указатели, объявленные таким образом, будут отличаться от указателей, объявленных "обычным" способом.
Умные указатели должны моделировать владение объектом и автоматически заботиться об уничтожении указанного объекта, когда последний (умный, владеющий) указатель на этот объект выпадает из области видимости.
Таким образом, вам не нужно запоминать действия delete
с объектами, размещенными динамически - деструктор интеллектуального указателя сделает это за вас - и не беспокоиться о том, не разыменовать ли (висящий) указатель на объект, который уже был уничтожен:
{
unique_ptr<int> p = make_unique<int>(42);
}
Теперь unique_ptr
это умный указатель, который моделирует уникальное владение, что означает, что в любой момент в вашей программе должен быть только один (владеющий) указатель на указанный объект - поэтому unique_ptr
его нельзя копировать.
Если вы используете интеллектуальные указатели таким образом, чтобы не нарушать неявный контракт, который они требуют от вас соблюдать, у вас будет гарантия, что утечка памяти не произойдет, и будет применяться правильная политика владения вашим объектом. Необработанные указатели не дают вам этой гарантии.
new int(3)
возвращает указатель на новоеint
, точно так же, какpd
был указатель на новоеdouble
.