I need to obtain auto_ptr from shared_ptr in my code. I can do reverse operation - convert auto_ptr to shared_ptr as shared_ptr has such constructor:
template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
Can I convert shared_ptr to auto_ptr? Or it is impossible by design?
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 .
Since the assignment-semantics was most-disliked feature, they wanted that feature to go away, but since there is code written that uses that semantics, (which standards-committee can not change), they had to let go of auto_ptr, instead of modifying it.
All the instances point to the same object, and share access to one "control block" that increments and decrements the reference count whenever a new shared_ptr is added, goes out of scope, or is reset. When the reference count reaches zero, the control block deletes the memory resource and itself.
The ownership of an object can only be shared with another shared_ptr by copy constructing or copy assigning its value to another shared_ptr . Constructing a new shared_ptr using the raw underlying pointer owned by another shared_ptr leads to undefined behavior.
It is impossible by design as the object may be shared with other shared pointer and thus "fetching" it to auto_ptr may lead to deleting referenced object.
For same reason shared_ptr has no "release" member function as auto_ptr.
Edit:
Even if shared_ptr had some kind of "release" method or allowed to remove its reference without destroying the object it would not work for following case (threads A, B):
A: {
A: int count = sp.use_count();
Context Switch
B: shared_ptr<bar> my_sp = weak_sp.lock();
B: // now use_count = 2 but A thinks it is 1
Context Switch
A: auto_ptr<bar> ap;
A: if(count == 1)
A: ap.reset(sp.release());
A: // actutally there is no sp.release but what if
A: ap->foo();
A: } // delete the object pointer by ap as it goes out of scope
Context Switch
B: my_sp->foo(); // Ooops - object is deleted!
A shared pointer can be shared by many things, you can't just take it from them all somehow. This is elaborated by Artyom and peoro.
One approach is to make a temporary auto_ptr
, and release it from handling the pointer at the end of the scope. dalle outlines a first approach, but this suffers from lack of exception-safety (might accidentally delete), and it cannot protect you from accidentally passing it to a function that's going to transfer ownership (where the delete falls out of our hands).
We can make our own wrapper to avoid this, though:
template <typename T>
class auto_ptr_facade
{
public:
auto_ptr_facade(shared_ptr<T> ptr) :
mPtr(ptr),
mAuto(ptr.get())
{}
~auto_ptr_facade()
{
// doesn't actually have ownership
mAuto.release();
}
// only expose as const, cannot be transferred
const auto_ptr<T>& get() const
{
return mAuto;
}
operator const auto_ptr<T>&() const
{
return get();
}
private:
auto_ptr_facade(const auto_ptr_facade&);
auto_ptr_facade& operator=(const auto_ptr_facade&);
shared_ptr<T> mPtr;
auto_ptr<T> mAuto;
};
Now you can treat a shared_ptr
like a const auto_ptr
, in a scope:
template <typename T>
void foo(shared_ptr<T> ptr)
{
auto_ptr_facade<T> a(ptr);
// use a
}
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