Let me pose my question through an example.
#include <memory>
std::unique_ptr<int> get_it() {
auto p = new int;
return p;
}
int main() {
auto up ( get_it() );
return 0;
}
This fails to compile with the following error:
a.cpp:5:9: error: could not convert ‘p’ from ‘int*’ to ‘std::unique_ptr<int>’
return p;
^
Why isn't there an automatic conversion from a raw pointer to a unique one here? And what should I be doing instead?
Motivation: I understand it's supposed to be good practice to use smart pointers for ownership to be clear; I'm getting a pointer (which I own) from somewhere, as an int*
in this case, and I (think I) want it in a unique_ptr
.
If you're considering commenting or adding your own answer, please address Herbert Sutter's arguments for this to be possible in proposal N4029.
The answer is two-fold. All the other answers, including a OP's self-answer, addressed only one half of it.
The pointer cannot be automatically converted because:
unique_ptr
's constructor from a pointer is declared explicit
, thus considered by the compiler only in explicit contexts. This is done so to prevent accidental dangerous conversions, where a unique_ptr
can hijack a pointer and delete it without programmer's knowledge. In general, not only for unique_ptr
, it is considered a good practice to declare all single-argument constructors as explicit
to prevent accidental conversions. return
explicit by Herb Sutter (N4029, N4074), and two "responses", arguing not to do so: N4094 by Howard Hinnant and Ville Voutilainen and N4131 by Filip Roséen. After several discussions and polls the issue was closed as NAD - not a defect.Currently, there are several workarounds:
return std::unique_ptr<int>{p};
or
return std::unique_ptr<int>(p);
In c++14, you can use auto-deduction of function return type as well:
auto get_it() {
auto p = new int;
return std::unique_ptr<int>(p);
}
Update: added a link to committee issue for the second point.