I've just discovered std::shared_ptr
's "aliasing constructor" and find myself asking "why doesn't std::unique_ptr have an corresponding one?
That is, if you want to allocate a Foo
so that you can pass its Bar
member to a function that should entirely manage the lifetime of the Foo
, wouldn't it be nice to be able to do so?
#include <memory>
struct B {}
struct A {
B b;
}
void f(std::unique_ptr<B> b);
std::unique_ptr<A> a = std::make_unique<A>();
std::unique_ptr<B> b { std::move(a), &(a->b) }; // a now invalid.
f(std::move(b)); // f now responsible for deleting the A.
This works with std::shared_ptr ( http://ideone.com/pDK1bc )
#include <iostream>
#include <memory>
#include <string>
struct B {
std::string s;
};
struct A {
B b;
A(std::string s) : b{s} {};
~A() { std::cout << "A deleted." << std::endl; }
};
void f(std::shared_ptr<B> b) {
std::cout << "in f, b->s = " << b->s << " (use_count=" << b.use_count() << ")" << std::endl;
}
int main() {
std::shared_ptr<A> a = std::make_shared<A>("hello");
std::shared_ptr<B> b { a, &(a->b) };
a.reset(); // a now invalid.
std::cout << "before f, b->s = " << b->s << " (use_count=" << b.use_count() << ")" << std::endl;
f(std::move(b)); // f now responsible for deleting the A.
std::cout << "after f" << std::endl;
return 0;
}
outputs the expected
before f, b->s = hello (use_count=1)
in f, b->s = hello (use_count=1)
A deleted.
after f
Is there a logical reason why such a thing wasn't included? And/or, is it a bad idea to emulate it with a unique_ptr<B>
with a custom deleter that deletes the A
?
In short, you can easily and efficiently convert a std::unique_ptr to std::shared_ptr but you cannot convert std::shared_ptr to std::unique_ptr .
Use unique_ptr when if you want to have single ownership(Exclusive) of resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. Use shared_ptr if you want to share ownership of resource .
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.
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.
I believe the “problem” is that, unlike std::shared_ptr
, std::unique_ptr
's deleter is not type-erased. The default deleter of std::unique_ptr<T>
(which has zero size, encoded into the type itself as a barely visible default type parameter) is simply [](T * p){ delete p; }
. But it is clear that a std::unique_ptr<B>
that was created via std::make_unique<B>
and one that was made by pointing to a B
member of an A
object cannot have the same deleter. The deleter for the latter case would have to do some pointer arithmetic to obtain the original A *
pointer back. Those two deleters could only have the same type if both would store an offset or an internal pointer to the original object. And that would no longer have zero size. std::unique_ptr
was designed to have zero overhead compared to doing new
and delete
manually, which is a Good Thing. I don't see any immediate drawbacks from using your own deleters that store that additional pointer, though I'd still have to come across a use-case where I'd find this useful.
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