Object instantination and initialization
-
Hi!
Should object fields be declared asObject obj;orObject* obj;with consequentnewin universal initializer list anddeletein destructor?
Why I am asking it - when fields are in the heap memory leaks are a lesser evil on modern PC with 8-16 GB RAM. But when I useObject obj;declaration in a field the risk of stack breakdown appears. -
Hi!
Should object fields be declared asObject obj;orObject* obj;with consequentnewin universal initializer list anddeletein destructor?
Why I am asking it - when fields are in the heap memory leaks are a lesser evil on modern PC with 8-16 GB RAM. But when I useObject obj;declaration in a field the risk of stack breakdown appears. -
@raven-worx
Thanks a lot for the link!
Sorry for my ignorance, I am C++ newcomer from Java and C#. Because of garrbage collecting in those languages, C++ memory model seems a bit complicated for me and I'm trying to understand it. -
when fields are in the heap memory leaks are a lesser evil on modern PC with 8-16 GB RAM
Memory leak, seg fault, stack overflow, and race condition are the 4 knights of the apocalypse. They are evil incarnate.
@Tikani said in Object instantination and initialization:
But when I use Object obj; declaration in a field the risk of stack breakdown appears.
Not really, internally Qt allocates almost everything on the heap so for the vast majority of classes
sizeof(OneQtClass)<=sizeof(int)+sizeof(void*)
@Tikani said in Object instantination and initialization:
and delete in destructor?
Qt normally uses a parent-child system with the ultimate parent allocated on the stack and its destructor will automatically delete all the children recursively. That's what
QObject::setParentand theparentargument to anyQObjectis for. ForQWidgets the parent-child relation is almost obligatory to lay out the visualisation correctly -
when fields are in the heap memory leaks are a lesser evil on modern PC with 8-16 GB RAM
Memory leak, seg fault, stack overflow, and race condition are the 4 knights of the apocalypse. They are evil incarnate.
@Tikani said in Object instantination and initialization:
But when I use Object obj; declaration in a field the risk of stack breakdown appears.
Not really, internally Qt allocates almost everything on the heap so for the vast majority of classes
sizeof(OneQtClass)<=sizeof(int)+sizeof(void*)
@Tikani said in Object instantination and initialization:
and delete in destructor?
Qt normally uses a parent-child system with the ultimate parent allocated on the stack and its destructor will automatically delete all the children recursively. That's what
QObject::setParentand theparentargument to anyQObjectis for. ForQWidgets the parent-child relation is almost obligatory to lay out the visualisation correctly -
@VRonin
If I understand you correctly, I should use RAII, i.e. to attempt to use automatic variables everywhere, avoiding the usage of manual dynamic memory management with help ofstd::unique_ptr,std::shared_ptr, "make"-functions and so on?@VRonin said in Interfaces, abstract, concrete classes and QObject:
This is the flowchart I normally follow, it covers 99% of the cases:
- is it a QObject?
- yes
- can you give it a parent? (for example
moveToThread()prevents the parent-child relationship)- yes: use a normal pointer and set the parent
- no: connect the
deleteLater()slot to some signal
- can you give it a parent? (for example
- no
- can multiple places share ownership of the object or pass ownership from one another? (e.g. in containes)
- yes: use
std::shared_ptr - no: use
std::unique_ptr
- yes: use
- can multiple places share ownership of the object or pass ownership from one another? (e.g. in containes)
- yes
If you need to use the pointer in a function that should not manage ownership but just access (read/write) the object (this covers 90% of use cases) then use a raw pointer argument (use
std::unique_ptr::get()orstd::shared_ptr::get()to retrieve the raw pointer from smart pointers) - is it a QObject?
-
@VRonin
If I understand you correctly, I should use RAII, i.e. to attempt to use automatic variables everywhere, avoiding the usage of manual dynamic memory management with help ofstd::unique_ptr,std::shared_ptr, "make"-functions and so on?@Tikani said in Object instantination and initialization:
If I understand you correctly, I should use RAII, i.e. to attempt to use automatic variables everywhere, avoiding the usage of manual dynamic memory management with help of std::unique_ptr, std::shared_ptr, "make"-functions and so on?
RAII extends to heap allocations too. It's a concept not a design pattern. The rule of thumb is use whatever's more natural, however esoteric this may sound. For example if you want to keep a
QStringor aQObjectas member, auto-storage's perfectly fine. If on the other hand you want to keep a dynamic list ofQObjects then you need to keep them as pointers and most of the time this'd mean you'd heap allocate the objects.PS. Because @VRonin raised the question, I advise caution when working with
QObjects and shared pointers (std::shared_ptrorQSharedPointer). Shared pointers are okay when an object manages its own lifetime, which forQObjectinstances is rather rare, so I'd shy away from using them most of the time.