When using unique_ptr, it is easy to forget to initialize the pointer, which may lead to a crash at runtime.
Why is unique_ptr defined with a default constructor leaving it pointing to nullptr? If it had always required a constructor parameter, the programmer would be forced to put it in the initializer list. Okay, if the default constructor is useful, wouldn't it also be useful with some kind of valid_unique_ptr that requires a constructor argument?
Should I subclass unique_ptr to force initialization, or maybe wrapping would be the way to go?
I'm a bit surprised I can't find this suggested or done anywhere...
Example:
#include "XTimerFactory.h"
struct MyClass {
MyClass(XTimerFactory& timerFactory)
: m_timer(timerFactory.createTimer()) // <- Crucial, or program will crash later
{ }
void start() { m_timer->start(100); }
private:
std::unique_ptr<XTimer> m_timer;
}
CodePudding user response:
Why is unique_ptr defined with a default constructor leaving it pointing to nullptr?
unique_ptr
models a pointer that is unique - not a pointer that always points to something. A default constructor (nullptr initialization) allows the class to be used in a lot more scenarios than a constructor always pointing to a valid instance.
For example, when you put unique pointers in a vector, it allows for a safe and easy implementation of the vector::resize
operation.
Should I subclass unique_ptr to force initialization, or maybe wrapping would be the way to go?
As a general rule, if the class doesn't have a virtual destructor, consider wrapping instead of subclassing it.
I'm a bit surprised I can't find this suggested or done anywhere...
Also see std::reference_wrapper and std::ref - though these do not take ownership.
Here's an implementation of something similar I did a while ago (shameless plug :D): https://codereview.stackexchange.com/questions/54371/polymorphic-owned-reference-wrapper-for-class-hierarchies
CodePudding user response:
Why is unique_ptr defined with a default constructor leaving it pointing to nullptr?
Probably because default constructible types are generally useful and convenient.
Should I subclass unique_ptr to force initialization, or maybe wrapping would be the way to go?
Both should work.
CodePudding user response:
When using unique_ptr, it is easy to forget to initialize the pointer, which may lead to a crash at runtime.
That is why you stick to auto uFoo = std::make_unikue<Foo>();
(since C 14).
This way your new variable will always be valid. Using a default constructor or a costructor that takes a raw pointer is useful when ownership is passed from some other than std::unqiue_ptr
object. So there will be no way to use std::make_unique
, otherwise always stick to it.
Moreover, std::unqie_ptr
by design may be nullptr
since there are release
and operator bool
, which would have no sence otherwise.