Why QT use the new operator excessively ?
-
I know about the dynamic memory and new operator but every QT documentation i read, mostly there is a new operator to instantiate an object. There must a good reason to do so but i don't know why.
Let's say i've created a tcpConnect class and i want to instantiate its object i.e.
tcpConnect tcp1 = new tcpConnect(&parent); // [option 1]
tcpConnect tcp2(&parent); // [option 2]Why QT use option 1 (mostly) ?
-
@pingal said in Why QT use the new operator excessively ?:
Why QT use option 1 (mostly) ?
Because the base class QObject is not copyable and the parent-child relationship will destroy the children automatically which would result in a double delete when the objects would be created on the stack.
-
Thanks for the helpful reply.
Can you kindly elaborate this statement "When quit subsequently goes out of scope, its destructor is called again, this time correctly, but the damage has already been done"
If destructor is called twice on an object, What consequence this have on program ? Is this an undefine behavior ?
-
@pingal said in Why QT use the new operator excessively ?:
What consequence this have on program ?
It will crash. Simply try it out.
-
It is true that it will crash if you try to call
delete
on an object on the stack (which Qt does automatically). This could be prevented (though not good style) by setting theparent
tonullptr
before the object goes out of scope.Qt made the decision right when they started to do things this way. And I believe there is a reason for this as well: Back then object oriented programming was a new hype. Qt goes all in to follow a pure object oriented approach. There is a lot of inheritance with
virtual
methods. Together with Liskov's substitution principle it is best in C++ to work with pointers (smart pointers didn't exist back then). This allows you to writeQWidget *w = new MyWidget(parent);
. If you don't use pointers here you easily introduce slicing. Polymorphism only works with pointers (and references). Lifetime management also plays a big role in choosing to use pointers (to objects on the heap). This is especially important for widgets which often outlive the scope of a function (things likeQMessageBox
might be the exception). Without pointers you are forced to have all your widgets as members of your class. With pointers I can create all widgets inside the constructor and connect all the signals and slot, then forget about the widgets because they are on the heap and the object list takes care of deleting everything in the end (because the parent is set properly).What could be different if Qt was invented today? OOP still requires that you use some sort of pointer. Today, it is considered bad style to use
new
directly in your code. Most likely we would have some sort of factory functions instead, likemake_qobject<MyWidget>(parent)
. Also, we might be using smart pointers instead of plain pointers. I am not entirely sure if this would be really an improvement for the readability of source code. There is the https://webtoolkit.eu called Wt (pronounce 'witty' since Qt is pronounced 'cute') which tries to copy Qt for web development in C++. They have made the switch to modern C++ now usingstd::unique_ptr
everywhere. The resulting code is quite verbose.TL;DR Proper OOP requires pointers in C++.
-
@SimonSchroeder said in Why QT use the new operator excessively ?:
Today, it is considered bad style to use new directly in your code
it is? 🤔 First I hear about it.
Usually people tend to heap allocate when they don't need to and don't care or know about the delete obligation. Usually new programmers that come from Java or other programming languages that implement a GC.Also personally not a fan of "smart pointers" in my programs I'm god, I decide over life and death of my objects 😈
Exception to this is the compiler and his magic wand
-
@J-Hilk said in Why QT use the new operator excessively ?:
it is? 🤔 First I hear about it.
Since modern C++ I perceive a push to get rid of plain
new
. (We are far from modern in our own codebase, so I don't follow this advice entirely.) It seems to be okay to use a plain pointer andnew
/delete
for member variables if the destructor definitely has thedelete
in it. Many times you can use a unique_ptr instead in these places to avoid accidental memory leaks.And when you actually start using smart pointers you should use
make_unique
andmake_shared
instead ofnew
. In some weird circumstances you might otherwise still leak memory despite using smart pointers. This is in the context of out-of-memory exceptions. Instead of learning when this might be a problem I agree it is better to always use the factory functions.That being said: This does not apply to your Qt code. Qt follows an incompatible approach to pointer management.
PS: For details of shared pointers and
new
see item 21 of Scott Meyers' "Effective Modern C++" (you can google for the PDF).