As shown here, std::unique_ptr
has two constexpr
constructors for null pointers:
constexpr unique_ptr();
constexpr unique_ptr( nullptr_t );
I have two questions for these two constructors:
Why do we need two? Can't we just declare one as:
constexpr unique_ptr( nullptr_t = nullptr );
Is the constexpr
really useful? I tried doing this in my code but it didn't compile (g++ 6.1.0, -std=c++14
):
constexpr std::unique_ptr<int> p;
// error: the type 'const std::unique_ptr<int>' of constexpr variable 'p'
// is not literal because 'std::unique_ptr<int>' has a non-trivial destructor
It can be assigned: class owner { std::unique_ptr<someObject> owned; public: owner() { owned=std::unique_ptr<someObject>(new someObject()); } };
In C++11 we can transfer the ownership of an object to another unique_ptr using std::move() . After the ownership transfer, the smart pointer that ceded the ownership becomes null and get() returns nullptr.
std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.
For (1), consider that it ensures that both the no-arg constructor unique_ptr()
and null-pointer constructor unique_ptr(nullptr_t)
have the same compile-time guarantees, i.e. both are constexpr
. We can see the difference in §20.8.1.2:
constexpr unique_ptr() noexcept;
explicit unique_ptr(pointer p) noexcept;
...
constexpr unique_ptr(nullptr_t) noexcept
: unique_ptr() { }
Why the two were not combined into a single constructor with a default value is likely historical contingency.
With regards to (2), why we should care about constexpr
despite having a non-trivial destructor, consider the answer given here:
constexpr
constructors can be used for constant initialization, which, as a form of static initialization, is guaranteed to happen before any dynamic initialization takes place.For example, given a global
std::mutex
:std::mutex mutex;
In a conforming implementation (read: not MSVC), constructors of other objects can safely lock and unlock
mutex
, becuasestd::mutex
's constructor isconstexpr
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With