Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is unique_ptr<T>(T*) explicit?

The following functions do not compile:

std::unique_ptr<int> foo() {     int* answer = new int(42);     return answer; }  std::unique_ptr<int> bar() {     return new int(42); } 

I find this a bit inconvenient. What was the rationale for making std::unique_ptr<T>(T*) explicit?

like image 624
fredoverflow Avatar asked Jul 06 '12 18:07

fredoverflow


People also ask

What does unique_ptr mean in C++?

(since C++11) 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.

Can unique_ptr be copied?

A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.

Is unique_ptr an example of Raii idiom?

yes, it's an RAII class.

What does unique_ptr get do?

std::unique_ptr::getReturns the stored pointer. The stored pointer points to the object managed by the unique_ptr, if any, or to nullptr if the unique_ptr is empty.


2 Answers

You don't want a managed pointer to grab ownership of a raw pointer implicitly, as that could end up in undefined behavior. Consider a function void f( int * ); and a call int * p = new int(5); f(p); delete p;. Now imagine that someone refactors f to take a managed pointer (of any type) and that implicit conversions were allowed: void f( std::unique_ptr<int> p ); if the implicit conversion is allowed, your code will compile but cause undefined behavior.

In the same way consider that the pointer might not be even dynamically allocated: int x = 5; f( &x );...

Acquisition of ownership is a important enough operation that it is better having it explicit: the programmer (and not the compiler) knows whether the resource should be managed through a smart pointer or not.

like image 89
David Rodríguez - dribeas Avatar answered Oct 23 '22 09:10

David Rodríguez - dribeas


Short answer:

The explicit constructor makes it difficult to write dangerous code. In other words, implicit constructor helps you to write dangerous code more easily.

Long answer:

If the constructor is implicit , then you could write such code easily:

void f(std::unique_ptr<int> param) {      //code  } //param will be destructed here, i.e when it goes out of scope   //the pointer which it manages will be destructed as well.  

Now see the dangerous part:

int *ptr = new int;  f(ptr);  //note that calling f is allowed if it is allowed: //std::unique_ptr<int> test = new int; //it is as if ptr is assigned to the parameter: //std::unique_ptr<int> test = ptr;  //DANGER *ptr = 10; //undefined behavior because ptr has been deleted by the unique_ptr! 

Please read the comments. It explains each part of the code snippet above.

When calling f() with a raw pointer, the programmer may not realize that the parameter type of f() is std::unique_ptr which will take ownership of the pointer and will delete it when it goes out of scope. Programmer on the other hand may use it, and delete it without even realizing that it has already been deleted! This all happens because of implicit conversion from raw pointer to std::unique_ptr.

Note that std::shared_ptr has explicit constructor for the very same reason.

like image 27
Nawaz Avatar answered Oct 23 '22 09:10

Nawaz