During C++03 we did not have unique_ptr
, so I had used the tr1::shared_ptr
instead.
Now, in C++11, in such cases, I am replacing calls like this:
tr1::shared_ptr<X> o(new X);
with
std::unique_ptr<X> o(new X);
Unfortunately, for some reason, I cannot replace cases containg a deleter, where the deleter is a function:
void special_delete(Y *p) { ... }
tr1::shared_ptr<Y> o(new Y(), special_delete);
std::unique_ptr<Y> o(new Y(), special_delete); // does not compile
std::unique_ptr<Y, std::function<void(Y*)> > o(new Y(), special_delete); // this compiles
Why does this happen? Is there a homogeneous way I can replace all shared_ptr constructors with unique_ptr constructors ?
I have created this , but I am not really happy about it..
template <class Y>
using unique_ptr_with_deleter = std::unique_ptr<Y, std::function<void(Y*)> >;
unique_ptr_with_deleter<Y> o(new Y(), special_delete); // this compiles
The shared_ptr
template type-erases the deleter. There's only one single type shared_ptr<T>
for any kind of deleter you want. It's a very heavy-weight (and expensive) tool.
By contrast, the unique_ptr
makes the deleter part of the type, and so it has no dynamic call overhead. A unique_ptr<T, D>
is very nearly as cheap as a raw pointer.
Note that you can construct a shared_ptr<T>
from a unique_ptr<T, D>
rvalue for any deleter type D
.
Random commentary on your solutions: neither solution is great. Using the function pointer as the deleter needlessly makes the deleter a dynamic part of your unique_ptr state. The std::function
case is even worse, using an entire type-erasing virtual dispatch mechanism for the deletion -- keeping in mind that you know statically how to delete!
The better solution is to make the deleter part of the type , not part of the value, by writing your own type:
struct YDeleter { void operator()(Y* p) { special_delete(p); } };
std::unique_ptr<Y, YDeleter> p(new Y); // or presumaby some special factory
That way, the entire deletion logic is known at compile time and can be inlined as much as possible, without additional function call indirection.
You should supply deleter type
std::unique_ptr<Y, decltype(&special_delete)> o{new Y{}, &special_delete};
Note that replacing tr1::shared_ptr<X> o(new X);
with std::unique_ptr<X> o(new X);
is not a good idea and is not supposed to work in general. std::unique_ptr
is more like a replacement for auto_ptr
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.