I wanted to use a smart pointer like shared_ptr of std library but where
it would be possible to delete the object for every shared_ptr that share it
without deleting those pointers.
For example if i use std::shared_ptr
shared_ptr<A> p1 = make_share<A>();
shared_ptr<A> p2 = shared_ptr<A>(p1);
p1.reset();
// now p2 still contain the object of type A
// instead of nullptr
Is there a way to do that or does some alternatives exist? Am i doing it wrong?
Absolutely. std::shared_ptr comes with std::weak_ptr, a pointer that can point to an object managed by a set of std::shared_ptrs and check whether it is still alive, but does not extends the object's lifetime.
You just have to keep the original std::shared_ptr to your object, and lend std::weak_ptrs to other users of that object. When the object must be destroyed, reset the std::shared_ptr, and all remaining std::weak_ptrs will be able to tell (they'll return null std::shared_ptrs when the users try to lock them).
Related
I'd like to wrap raw pointer member to some smart pointer to prevent deleting inside a developing class. Owner of the object under pointer is outside of class. So, looks like boost::shared_ptr and std::auto_ptr does not fit. The following is a reduced example:
class Foo {
boost::weak_ptr<Bar> m_bar;
public:
void setBar(const Bar *bar) { // bar created on heap
m_bar = bar; // naturally compilation error
}
};
Of course, it induces compilation error. What is a correct way to initialize weak_ptr from a raw pointer (if exist)?
You can't do that, you can only create a weak_ptr out of a shared_ptr or another weak_ptr.
So the idea would be that the owner of the pointer hold a shared_ptr instead of a raw pointer, and everything should be ok.
The only way to do it is by getting hold of a shared_ptr or weak_ptr that owns the pointer, otherwise the weak_ptr has no way to find the existing owner in order to share ownership with it.
The only way to get a shared_ptr from a raw pointer that is already owned by another shared_ptr is if Bar derives from enable_shared_from_this<Bar>, then you can do
m_bar = bar->shared_from_this();
The purpose of a weak pointer is to be unable to use the raw pointer if it had been deleted. However, if you have a raw pointer, the weak pointer has no way to know that it was deleted. Instead, you must have a shared_ptr somewhere which "owns" the raw pointer. Then you can create a weak_ptr which references the shared_ptr.
When the shared_ptr goes out of scope and is the last "strong" smart pointer, it will automatically delete the raw pointer. Then, when you try to lock the weak_ptr, it will see that there is no "strong" pointer remaining and therefore the object does not exist.
Everything you've said seems perfectly reasonable, except for one thing:
void setBar(const Bar *bar)
This shouldn't take a raw pointer. It should take a weak_ptr ideally, or possibly a shared_ptr if you have some compelling argument.
The actual owner of the object in question should construct the weak_ptr and than call setBar with that. This preserves the ownership semantics. It looks like what you're doing is having the owning object take a raw pointer and pass that to setBar. This creates a semantic gap in the ownership of the object.
Pass shared pointer instead of raw pointer, and create your weak pointer from that shared pointer. This is really the only way if owner of the pointer is outside of a class.
I have a class A which has a field of type std::unique_ptr:
class A
{
public:
std::unique_ptr pointer;
// class body
};
And somewhere in code, I'm using few std::shared_ptrs which point to the same object. Now what I'd like to achieve is to move ownership to this std::unique_ptr in my class, so that if all shared_ptrs will be destroyed, my object will stay alive as long as this unique_ptr will stay alive.
My question is - is it possible to move ownership from std::shared_ptr to std::unique_ptr and if yes, how can I do this?
Logically such a scenario doesn't make sense to me.
Suppose for a while that it is possible to transfer the ownership, but you could do that only when you're sure that there is only one shared_ptr alives; if that is the case, then you can still use shared_ptr as member of A and pretend that it is unique_ptr.
And then you commented:
That's true, I could create shared_ptr in A class. I think I misunderstood a concept a bit again. I wanted to behave it in this way: if unique_ptr dies, the object itself dies too, even though shared_ptrs still point to it, but that's silly as they wouldn't know that object itself was destroyed and therefore they wouldn't be nullptrs.
In that case, you're looking at the wrong smart pointer. What you probably need is called std::weak_ptr. If so, then make sure you use one std::shared_ptr and all others as std::weak_ptr.
I need to use a shared_ptr here because I can't change the API.
Foo1 *foo1 = new Foo1(...);
shared_ptr<Foo2> foo2(foo1);
Is the shared_ptr here going to handle freeing the memory used by foo1? If I understand correctly, I shouldn't have to call delete on foo1 correct?
Yes. You are correct, but the correct way to initialise foo2 is:
std::shared_ptr<Foo2> foo2 = std::make_shared<Foo1>();
Herb Sutter discusses the reasons why you should use std::make_shared<>() here:
https://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/
You shouldn't call delete on foo1.
Better you shouldn't create foo1. Only foo2:
shared_ptr<Foo2> foo2(new Foo1(...));
std::shared_ptr: http://en.cppreference.com/w/cpp/memory/shared_ptr
std::shared_ptr is a smart pointer that retains shared ownership of an object through a pointer.
If you do not need this pointer to be shared - consider to use std::unique_ptr
std::unique_ptr: http://en.cppreference.com/w/cpp/memory/unique_ptr
std::unique_ptr is a smart pointer that: retains sole ownership of an
object through a pointer, and destroys the pointed-to object when the
unique_ptr goes out of scope.
Correct. The smart pointers provide ownership semantics. In particular, the semantics provided by std::shared_ptr are such that the object will be deleted once the last shared_ptr pointing to it is destroyed. shared_ptr keeps a reference count (how many shared_ptrs are referring to the object) and when it reaches 0, it deletes the object.
Will the smart pointer or scoped pointers delete an object when the class has no destructor
If not, why not just leave the scope and let the object be deleted by itself?
All class members are deleted even if you don't have a destructor when the instance is deleted. Memory leaks occur when you deal with pointers:
class A
{
private:
B* b;
};
In this case, b itself will be destroyed when the instance of A is deleted, but the memory it points to will not.
class A
{
private:
SmartPtr<B> b;
};
In the case of smart pointers, which usually have some reference counting and memory cleanup in the destructor, the memory it points to will be explicitly destroyed by its destructor, and the destructor of the smart pointer will be implicitly called when the instance of the containing class is destroyed.
yes. that s what smart pointers are used for.
http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/smart_ptr.htm
http://en.wikipedia.org/wiki/Smart_pointer
What is a smart pointer and when should I use one?
Yes, smart pointer deletes the object irrespective of whether class has destructor or not. Note that smart pointers are used with objects allocated on heap (using new) and these object won't release memory when they go out of scope, you need to explicitly delete them. Smart pointers will remove this process of explicitly deleting them.
The pointer to the object itself will be deleted. However if there is any dynamically allocated data in the class it will not get freed. The idea of having a destructor is to be able to post-process the class object and mainly - free any resources taken.
new and delete do two things.
new allocates memory and gets an object to construct itself in that memory space.
delete first gets the object to destruct itself then releases the memory.
Note that some smart pointers can be given a custom deleter which doesn't call delete on the object but whatever you ask it to do. There may be occasions when you wish to pass it a no-op.
Your point is well taken; there aren't that many uses for smart pointers
in C++, since most of the time where they might be relevant, you'd be
better off using value semantics, and copying. In the case of
scoped_ptr, the most frequent use is when the actual object is
polymorphic:
scoped_ptr<Base> pObj = condition
? static_cast<Base*>( new Derived1 )
: static_cast<Base*>( new Derived2 );
(Regretfully, at least one of the static_cast is necessary.)
If you are dealing with a container of polymorphic objects, you'll need
shared_ptr instead, and if you're returning a polymorphic object, or
otherwise passing it around, you will use unique_ptr if you can
guarantee its availability, and auto_ptr otherwise—in some cases
where you're passing it around, shared_ptr might be more appropriate.
In the case of returning an object or passing it around, the cost of
copying it might also be a motive for using a smart pointer, even if the
object isn't polymorphic. In such cases, I'd still use value semantics
(i.e. copying and assigning the object itself) unless I had a
performance problem.
Note that smart pointers aren't only used for memory management. I
regularly use auto_ptr in the interface of queues between threads:
once the object has been inserted into the queue, it no longer belongs
to the sending thread; auto_ptr expresses these semantics exactly,
with the auto_ptr in the sending thread becoming invalid. Or a
modifiable singleton (something which should be very, very rare) might
acquire a lock in its instance function, and return a shared_ptr
which frees the lock in its final destructor. I've also used smart
pointers in one or two cases to ensure transactional semantics: in one
case, for example, the objects were in a number of different sets (which
held pointers to them, of course), ordered according to different
criteria. To modify an object, you acquired a shared pointer to it; the
function which returned this shared pointer also removed the objects
from the sets, so that you could safely modify the key values as well,
and the final destructor reinserted them into the sets according to the
new keys. And so on—there are any number of uses for smart
pointers that have nothing to do with memory management or object
lifetime.
Im working on this project,
The problem Im having is that the an object, does not really get deleted when I need it to be because it has a couple of shared pointers pointing to it.
How do I solve this,please help.
This is by design. As long as an object is owned by one or more shared_ptr smart pointers, it will not be destroyed. Ownership of the object is shared by all of the smart pointers that have ownership and the object can't be destroyed until all of the owners are done with it. This is what shared ownership is.
If you want to be able to destroy the object while there are still some references to it, you can use weak_ptr for those references.
You can decrease the use_count of a shared_ptr by using its reset() method.
If you do this for every pointer which holds the instance, the last reset() will destroy the object it points to.
shared_ptr<Class> myPointer1( new Class() ); //myPointer holds an instance of Class
shared_ptr<Class> myPointer2 = myPointer1; //use_count == 2
myPointer1.reset(); //use_count == 1
myPointer2.reset(); //instance of class will be destroyed
But you probably have a problem with you design, shared_ptr should automatically go out of focus when certain objects are destroyed or methods end. Perhaps you should have a look at the points where the shared_ptrs still hold pointers to the object and check if they shouldn't hold the object anymore.