Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use std::make_unique in C++17?

As far as I understand, C++14 introduced std::make_unique because, as a result of the parameter evaluation order not being specified, this was unsafe:

f(std::unique_ptr<MyClass>(new MyClass(param)), g()); // Syntax A 

(Explanation: if the evaluation first allocates the memory for the raw pointer, then calls g() and an exception is thrown before the std::unique_ptr construction, then the memory is leaked.)

Calling std::make_unique was a way to constrain the call order, thus making things safe:

f(std::make_unique<MyClass>(param), g());             // Syntax B 

Since then, C++17 has clarified the evaluation order, making Syntax A safe too, so here's my question: is there still a reason to use std::make_unique over std::unique_ptr's constructor in C++17? Can you give some examples?

As of now, the only reason I can imagine is that it allows to type MyClass only once (assuming you don't need to rely on polymorphism with std::unique_ptr<Base>(new Derived(param))). However, that seems like a pretty weak reason, especially when std::make_unique doesn't allow to specify a deleter while std::unique_ptr's constructor does.

And just to be clear, I'm not advocating in favor of removing std::make_unique from the Standard Library (keeping it makes sense at least for backward compatibility), but rather wondering if there are still situations in which it is strongly preferred to std::unique_ptr

like image 211
Eternal Avatar asked Dec 20 '18 14:12

Eternal


People also ask

Why should I use Make_unique?

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.

What does Make_unique return C++?

class A {} std::unique_ptr<A> f() { return std::make_unique<A>(); } std::unique_ptr<A> a = f(); Hmm, if I remember correctly, a function in C++ returns a copy of the returned object. A function f returns a copy of std::unique_ptr constructed by std::make_unique . How is it possible?

When was Make_unique introduced?

Introduction. The std::make_unique function was introduced in the C++14 standard.

Does Make_unique use new?

The addition of make_unique finally means we can tell people to 'never' use new rather than the previous rule to “'never' use new except when you make a unique_ptr”.


2 Answers

You're right that the main reason was removed. There are still the don't use new guidelines and that it is less typing reasons (don't have to repeat the type or use the word new). Admittedly those aren't strong arguments but I really like not seeing new in my code.

Also don't forget about consistency. You absolutely should be using make_shared so using make_unique is natural and fits the pattern. It's then trivial to change std::make_unique<MyClass>(param) to std::make_shared<MyClass>(param) (or the reverse) where the syntax A requires much more of a rewrite.

like image 152
NathanOliver Avatar answered Oct 04 '22 08:10

NathanOliver


make_unique distinguishes T from T[] and T[N], unique_ptr(new ...) does not.

You can easily get undefined behaviour by passing a pointer that was new[]ed to a unique_ptr<T>, or by passing a pointer that was newed to a unique_ptr<T[]>.

like image 37
Caleth Avatar answered Oct 04 '22 08:10

Caleth