В чем причина явного конструктора std :: unique_ptr & lt; T & gt; из T *?

Как std::unique_ptr обеспечивает удобный способ избежать утечек памяти и обеспечить безопасность исключений; разумно передавать их, а не исходные указатели. Таким образом, можно хотеть (член) функции с подписью как

std::unique_ptr<some_type> foo(some data);

К сожалению, при реализации такой функции нельзя просто

std::unique_ptr<some_type> foo(some data)
{
return { new some_type(data) };                  // error
}

но должен вместо

std::unique_ptr<some_type> foo(some data)
{
return std::move( std::unique_ptr<some_type>( new some_type(data) ) );   // awkward
}

потому что конструктор unique_ptr::unique_ptr(pointer) является explicit, В чем причина этого конструктора explicit?

Одна мотивация, чтобы сделать конструкторов explicit это для защиты от непреднамеренного неявного преобразования типов. Тем не менее, как unique_ptr не может быть передано по значению, это не должно быть проблемой, не так ли?

12

Решение

unique_ptr вступает во владение переданным указателем. Принятие владения должно быть явным — вы не хотите, чтобы какой-то указатель «волшебным образом» становился владельцем (и удалялся) каким-то классом (это было одной из проблем с устаревшими std::auto_ptr).

например:

void fun(std::unique_ptr<X> a) { .... }
X x;
fun(&x); // BOOM, deleting object on stack, fortunately it does not compile
fun(std::unique_ptr<X>(&x)); // compiles, but it's explicit and error is clearly visible

пожалуйста, обратите внимание, что std::move не требуется в return оператор (специальное языковое исключение — локальные переменные как return аргументы могут рассматриваться как «перемещенные»).

Также — в C ++ 14 вы можете использовать std::make_unique чтобы сделать его менее неловким:

return std::make_unique<some_data>(some_data_argument1, arg2);

(его также легко можно добавить в C ++ 11 — читайте Вот)

19

Другие решения

Аргументы, принимающие уникальные ptr, не должны молча владеть указателями.

Таким образом, ctor является явным.

Чтобы вернуться, попробуйте make_unique<foo>(?) вместо {new foo(?)},

5

По вопросам рекламы [email protected]