For example, can it be used in Qt for the following?
gsl::owner<QWidget*> w{new QWidget{parent}}
In this example, the ownership is shared by the new-site and the parent, because the code who has new-ed the object can delete w, and W's destructor will take itself out of parent children list. However, if w is not deleted at the new-site, then parent will delete it in its destructor.
Is this an example of shared ownership, and
can gsl::owner be used for it?
Is this an example of shared ownership
No, you have two places claiming unique ownership.
can gsl::owner be used for it
If w can outlive the object pointed to by parent, then it might become invalid, leading to undefined behaviour.
If you want a pointer type that interfaces with Qt's parent-child ownership, use QPointer
In this example, the ownership is shared by the new-site and the parent, because the code who has new-ed the object can delete w, and W's destructor will take itself out of parent children list. However, if w is not deleted at the new-site, then parent will delete it in its destructor.
This is wrong. The code that has created this object should not delete it unless it is absolutely sure that the parent is still alive, otherwise you will get double-free errors (because parent would have freed the object already).
The correct solution is to use QPointer as mentioned in the other answer.
Related
Im thinking of starting using smart pointers in my qt work.The thing that confuses me how smart pointers would go with Qt garbage collection. The whole Qt stands on idiom that child QObject constructs with QObject* parent as ctor argument and therefore enables garbage collection.
For example:
QWidget* mWidget = new QWidget(this);//Here we not only
//ensure that mWidget will be deleted
//when its parent is deleted, but also tell qt,
//that mWidget is not a window, but belongs to
//parent's layout
Now if i want to wrap mWidget into the smart pointer.
typedef QScopedPointer<QWidget> WidgPtr;
WidgPtr mWidget = WidgPtr(new QWidget(this));
But now when parent's dtor is called it will call delete on mWidget's pointer twice. First due to garbage collection, second when smart pointer dtor is called.
Of course we can construct mWidget without parent and then change some flags to turn off window behaviour or call setParent() (But then again mWidget will be deleted twice). But to me its too much to do such a complex initialization only to be able to use smart pointers instead of raw pointers.
Or maybe i miss something?
Thanks.
QScopedPointer and QSharedPointer are not aware of whether their target object lives or dies, so if you keep the smart pointer anywhere else than among member variables, then yes, in your case destructor might be called twice. That's why these kinds of smart pointers are badly suited for QObjects (but they can still be useful when your object doesn't have a parent).
If you need to keep a guarded pointer to QObject, use QPointer: it will become null once the object is destroyed, so you can delete it at any moment without fear of causing any mayhem. But remember that QPointer will NOT destroy referenced object in destructor. In most cases you should build hierarchies of QObjects and just let the ownership system clean up the memory.
According to the Qt documentation:
QObjects organize themselves in object trees. When you create a
QObject with another object as parent, the object will automatically
add itself to the parent's children() list. The parent takes ownership
of the object; i.e., it will automatically delete its children in its
destructor.
For me that implies when a QObject is being deleted, it goes through and calls delete on all the pointers it stores in its children list.
However, it is not necessary for children to be dynamically allocated, and it is perfectly legal to build QObject trees with stack allocated objects.
According to standard specifications, calling delete on a pointer that does not point to a dynamically allocated object is undefined behavior, which may result in anything from "nothing" to a program crash.
IMO it is unlikely for QObject, which is pretty much the backbone of the almost the entire collection of Qt classes to rely on something that could produce undefined behavior.
So, does QObject distinguish between stack and heap allocated children when deleting? And if so, how exactly?
However, it is not necessary for children to be dynamically allocated,
and it is perfectly legal to build QObject trees with stack allocated
objects.
No. See QObject::~QObject():
Warning: All child objects are deleted. If any of these objects are on
the stack or global, sooner or later your program will crash.
How does the dynamically allocated pointers in QT coding are destroyed because we don't write a specific destructor for them?
To expand on Neox's answer, Qt has two methods for object management:
QObject tree structure
Managed pointer classes
And the two don't really mix very well for reasons which will become apparent.
QObjects can either be 'free' or have a parent. When a QObject has its parent set (either by providing the QObject constructor with a pointer to another QObject, or by calling setParent()) the parent QObject becomes the owner of the child QObject and will make sure any of its children are destroyed when it is. There are also several methods available to inspect child/parent relationships.
A separate method of managing dynamically allocated objects are the managed pointer classes which this paper explains quite well. To summarise though:
"The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon destruction" and is therefore good when you need objects which have clear and obvious ownership and lifetime.
"The QSharedPointer class holds a strong reference to a shared pointer [and] will delete the pointer it is holding when it goes out of scope, provided no other QSharedPointer objects are referencing it" and is therefore good when ownership is not as clear cut, but you want to make sure it doesn't get lost and become a memory leak. QWeakPointer can be used to share the pointer without implying any ownership.
As you can see, some of the guarded pointer classes can be used with a QObject tree, but you should make sure you read and understand the documentation thoroughly before doing so or you may end up with a corrupt data structure.
The short answer is:
QObjects organize themselves in object trees. When you create a QObject with another object as parent, it's added to the parent's children() list, and is deleted when the parent is.
Qt has a good docu about object hierarchy and ownership within the framework. You can read it here
I've been building a system with a parent object, where it creates various child objects, and each child object requires a master object to function. Now, so far, I've been creating shared_ptr<Parent> and Child*, so when the creator of Parent and all the Childs are gone, the Parent goes too.
But I'm re-designing my API so that Child can be created on the stack (previously it was just the heap). Now I'm unsure about what to do with Parents, as I don't see why they shouldn't also be creatable on the stack- in terms of their actual function- but what happens if Parent is destroyed and then someone tries to use a Child that they moved, copied, or allocated on the heap? Should I just throw an exception? Skip performing the operation? Or just stick to allocating Parents on the heap?
Here's the problem sentence
if Parent is destroyed and then someone tries to use a Child ...
If this is possible then you have shared ownership, which implies creation on the heap.
So, either you stick to heap allocation or drop the shared ownership semantics. There is no other way. weak_ptr is merely away of advertising the state of a shared object.
If you really want to do what you're advertising:
if Parent is destroyed and then someone tries to use a Child ...
This is going to cause a problem as #spraff mentioned.
The way to achieve what you are saying is to also make the Child a shared_ptr and allow a shared ownership between the Parent and also whatever else is trying to use the child...
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.