Trying to load a frame of widgets using a shared pointer
-
Hi,
I'm hoping you can help me. I built a library that is shared by many applications. This library contains a host of widgets which gives the users certain common options, so instead of creating the same widgets across applications they simply load the library and have all the widgets and logic already built in. The ui file was built in Qtcreator.
If I call my library myWidgeLibrary, I was able to load the widgets in this manner
WidgetLibrary *myWidgetLibrary; myWidgetLibrary = new WidgetLibary; //to load the library in the app I did something like this which works fine. ui->appGridLayout->addWidget( myWidgetLibrary, 0, 0, 1, 1 );
So the above loads the widgetLibary into a gridLayout inside the users application.
Now this is the issue. The people I work with does not like to use naked pointers.
so "WidgetLibrary *myWidgetLibrary" is very bad.
instead, they prefer the call the WidgetLibrary using a shared pointer.std::shared_ptr< WidgetLibrary > myWidgetLibrary ; ui->appGridLayout->addWidget( myWidgetLibrary, 0, 0, 1, 1 );
But as you imagine that doesn't work and I get an error "No matching member function for call to 'addWidget' "
I think because widgets are created with naked pointers and I'm trying to add them as a shared pointer.Would you know how I can fix this? What do I need to do in the library or in my main application to allow me to load it using a shared pointer?
Any help would be appreciated!
Thanks
-
Hi,
I'm hoping you can help me. I built a library that is shared by many applications. This library contains a host of widgets which gives the users certain common options, so instead of creating the same widgets across applications they simply load the library and have all the widgets and logic already built in. The ui file was built in Qtcreator.
If I call my library myWidgeLibrary, I was able to load the widgets in this manner
WidgetLibrary *myWidgetLibrary; myWidgetLibrary = new WidgetLibary; //to load the library in the app I did something like this which works fine. ui->appGridLayout->addWidget( myWidgetLibrary, 0, 0, 1, 1 );
So the above loads the widgetLibary into a gridLayout inside the users application.
Now this is the issue. The people I work with does not like to use naked pointers.
so "WidgetLibrary *myWidgetLibrary" is very bad.
instead, they prefer the call the WidgetLibrary using a shared pointer.std::shared_ptr< WidgetLibrary > myWidgetLibrary ; ui->appGridLayout->addWidget( myWidgetLibrary, 0, 0, 1, 1 );
But as you imagine that doesn't work and I get an error "No matching member function for call to 'addWidget' "
I think because widgets are created with naked pointers and I'm trying to add them as a shared pointer.Would you know how I can fix this? What do I need to do in the library or in my main application to allow me to load it using a shared pointer?
Any help would be appreciated!
Thanks
@leinad said in Trying to load a frame of widgets using a shared pointer:
Would you know how I can fix this
Pass the naked pointer with .get() and wonder why it crashes as soon as your shared pointer goes out of scope.
in other words - don't use a shared pointer for QObjects. -
As @Christian-Ehrlicher wrote,
std::shared_ptr
and QObjects don't mix. The reason for that is that once you add a widget to another widget's layout - the later will become the former' owner in the QObject hierarchy, and will therefore consider itself responsible to delete it when the time comes. At the same time theshared_ptr
still thinks it manages the widget and will try to delete it when it deems necessary too. This means that one of the pointers to the widget pointer will become dangling at some point, which is a disaster for the program.For environments that have a "no bare pointers" rule, you can use
std::unique_ptr
to allocate objects (viastd::make_unique
), and then when you pass them to Qt ownership use therelease
method to have the unique pointer "give up" its' managed object. That said such a rule makes life a lot harder than needed in Qt code bases. -
Pointers in Qt look naked, but they are not. As said before widgets own all their child widgets and handle them being cleaned up. And certainly there is a place in C++ for non-owning raw pointers. Don't use shared_ptr in every single place. If you call a function it is okay if it expects a raw pointer while you have the shared_ptr. If you start copying the shared_ptr into every function you call you will loose a lot of performance. Sure, you can use a
const std::shared_ptr &
instead, but that is also defeating the purpose and no different than raw pointers. Raw pointers are not evil, but owning raw pointers are.In your tiny example the raw pointer is owning for just a very short time (most likely only for the the two lines if there is nothing in between). If you want to be pedantic you could follow the approach of @IgKh and use a std::unique_ptr. But, it is most certainly mandatory to use std::make_unique to create the object. Otherwise allocation might still fail and throw an exception and the unique_ptr does not become the owner and the destructor of partially created objects (if you are using inheritance) are not called. You see from this that just using smart pointers does not always solve the problem because you can still use them wrong if you don't understand everything about them. And there is very little gain in your specific case in using a smart pointer (correctly). And for most programs it is true that they don't catch out-of-memory errors and handle them properly to free up some memory.
I would personally never use smart pointers with Qt widget types. (Unless Qt in new versions rewrites their library to make them mandatory.)