It is recommended to use the 'make_unique/make_shared' function to create smart pointers. The analyzer recommends that you create a smart pointer by calling the 'make_unique' / 'make_shared' function rather than by calling a constructor accepting a raw pointer to the resource as a parameter.
A little late, but make_unique can itself throw according to cppreference: make_unique "may throw std::bad_alloc or any exception thrown by the constructor of T. If an exception is thrown, this function has no effect." So how is that exception safe?
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.
Nullability - a scoped_ptr or unique_ptr can be null, a value object can never be. Polymorphism - a value object is always exactly its static type, but you can substitute in different derived types for a unique_ptr. The previously-held object is automatically destroyed when you do this.
make_unique
teaches users "never say new
/delete
and
new[]
/delete[]
" without disclaimers.
make_unique
shares two advantages with make_shared
(excluding the third advantage, increased efficiency). First, unique_ptr<LongTypeName> up(new LongTypeName(args))
must mention LongTypeName
twice, while auto up = make_unique<LongTypeName>(args)
mentions it once.
make_unique
prevents the unspecified-evaluation-order
leak triggered by expressions like foo(unique_ptr<X>(new X)
,
unique_ptr<Y>(new Y))
. (Following the advice "never say new
" is simpler than
"never say new
, unless you immediately give it to a named unique_ptr
".)
make_unique
is carefully implemented for exception safety and is recommended over directly calling unique_ptr
constructors.
make_unique
make_unique
if you need a custom deleter or are adopting a raw pointer from elsewhere.std::make_unique
.The difference is that std::make_unique
returns an object of type std::unique_ptr
and new
returns a pointer to the created object. For memory allocation failures, they will both throw. Hold on, it's not that simple. Read further.
Consider such a function below:
void func(ClassA* a, ClassB* b){
......
}
When you make a call like func(new A(), new B())
; The compiler may choose to evaluate the function arguments from left to right, or in any order it so wishes. Let's assume left to right evaluation: What happens when the first new
expression succeeds but the second new
expression throws?
The real danger here is when you catch such exception; Yes, you may have caught the exception thrown by new B()
, and resume normal execution, but new A()
already succeeded, and its memory will be silently leaked. Nobody to clean it up... * sobs...
But with make_unique
, you cannot have a leak because, stack unwinding will happen ( and the destructor of the previously created object will run). Hence, having a preference for make_unique
will constrain you towards exception safety. In this case, std::make_unique
provides a "Basic Exception Safety" that the memory allocated and object created by new
will never be orphaned no matter what. Even till the ends of time... :-)
You should read Herb Sutter GoTW102
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