c++c++11unique-ptrexplicit-constructor

What's the reasoning behind std::unique_ptr<T>'s constructor from T* being explicit?


As std::unique_ptr provides a handy way to avoid memory leaks and ensure exception safety, it is sensible to pass them around rather than raw pointers. Thus, one may want (member) functions with a signature like

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

Unfortunately, when implementing such a function, one cannot simply

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

but must instead

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

because the constructor unique_ptr::unique_ptr(pointer) is explicit. What is the reasoning behind this constructor being explicit?

One motivation to make constructors explicit is to guard against unintended implicit type conversion. However, as unique_ptr cannot be passed by value, this should not really be a problem, should it?


Solution

  • unique_ptr takes ownership of passed pointer. Taking ownership should be explicit - you don't want some pointer to 'magically' become owned (and deleted) by some class (that was one of issues with deprecated std::auto_ptr).

    for example:

    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
    

    please note, that std::move is not required in return statement (special language exception - local variables as return arguments can be treated as 'moved').

    Also - in C++14 you can use std::make_unique to make it less awkward:

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

    (it can be also easily added to C++11 - read here)