4

I'm wondering if Qt puts things like "version 1" of the below code on the heap? In version 1, would dirStuff be placed on the stack or the heap by Qt? I'm asking because I have a feeling that Java puts all data structures on the heap... Not sure cause I don't remember ever having to think about this with Java.

version 1

QFileInfoList dirStuff = dir.entryInfoList(QDir::Dirs | QDir::Files | 
                         QDir::NoDotAndDotDot | QDir::System | QDir::Hidden);

version 2

QFileInfoList * dirStuff = new QFileInfoList();
*dirStuff = dir->entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot |
                                       QDir::System | QDir::Hidden);

Of course, I'll assume that version 2 is on the heap, but I'm wondering if...

delete dirStuff;

would really clean up "version 2" of dirStuff because it is not a regular object but probably a linked list. The cleaning up of which I think could be problematic, so I'm wondering if there is a special Qt way I should be cleaning up a Qt data structure like a QFileInfoList on the heap... or if the regular old C++ delete is good enough.

Freedom_Ben
  • 11,247
  • 10
  • 69
  • 89
user440297
  • 1,181
  • 4
  • 23
  • 33

2 Answers2

4

Containers like QList, QVector etc. and data structures like QString, QByteArray, QFileInfo... can be created both on the stack and on the heap with new/delete. delete is always enough; Any special cleanup needed would be encapsulated in the destructor.

That said, all the classes I mentioned above should be created on the stack if there is not a strong reason for the heap (and there usually isn't). They are supposed to be passed by value/const reference instead of by reference or pointer. They are implicitely shared (copy-on-write), which means copies without modification are cheap. Opposed to java, where you pass almost everything by reference, here the objects are semantical values. Example:

 //getter returns copy
 QList<Something> Foo::somethings() const {
     return m_somethings;
 }

 //list is passed by const reference to the setter 
 void Foo::setSomethings( const QList<Something>& l ) {
     m_somethings = l;
 }
 ...

 //Get the value of m_somethings, creating a (yet unmodified) copy. 
 QList<Something> list = somethings();
 //modify the copy. m_somethings is _not_ modified (different object).  
 list.append( Something( "Something else" ) );
 //Write changes back to m_somethings
 setSomethings( list );

See also this answer to a similar question, explaining why QObjects are different.

Community
  • 1
  • 1
Frank Osterfeld
  • 24,815
  • 5
  • 58
  • 70
  • Thanks. Let me stir the pot a bit based on my understanding of your post. (1) The benefit of implicit sharing for Qt data structures is that while no writing/modification has taken place we are not dealing with stand alone copies (list is not stand alone against m_somethings, it is actually the same thing physically) and thus memory burden is reduced. What confuses me is that in general when I think of a data structure like QFileInfoList or QStringList it is hard for me to imagine a situation when I am not writting to the list... – user440297 May 18 '11 at 11:51
  • [continued]...as such, if we are to assume that not much time goes bye without me not writing to the data structure, am I wrong in assuming also that this benefit of implicit sharing is somewhat limited for such a case? – user440297 May 18 '11 at 11:54
  • [quote]That said, all the classes I mentioned above should be created on the stack if there is not a strong reason for the heap (and there usually isn't).[/quote] The reason I am concerned with regard to "version 1" of my code above is because I wrote a recursive function that deletes all content in a dir. It relies on QDir::entryInfoList on EACH recursive call after a dir is found. If the file structure was huge (millions of files in many sub-folders) I am worried that I would overflow the stack. ... – user440297 May 18 '11 at 12:06
  • [continued]... Granted I am not writing to the list in this scenario but I am creating potentially hundreds of such list. So, should I not worry about this because internally the list is actually on the heap in "Version 1" and only the handle object is on the stack...or is this a case where I should use "version 2"? – user440297 May 18 '11 at 12:06
  • [quote]They are supposed to be passed by value/const reference instead of by reference or pointer.[/quote] I apologize for all the comments but I wanted to be 100% clear. The const reference assumes that I don't want to mod the list being passed into the function, does it not? If we assume that a function has the primary intent to modify a list, would it still not be recommended to pass in a pointer or a non const reference to a list? And if it is in such a case ideal to use a ptr or a non-const ref, which one would you use considering Qt's internals? – user440297 May 18 '11 at 12:16
3

In version 1, the object will be put on the stack, but it may internally point to data allocated in the heap (if it dynamically allocates memory inside its methods).

About version 2, delete would clean it up because it calls QFileInfoList's destructor, in which the Qt library does what's necessary to remove every resource that won't be used anymore.

Gabriel
  • 1,803
  • 1
  • 13
  • 18
  • thanks. It is Qt's policy of what it does internally when it comes to data structures that I'm not sure about. If I make a Qlist is the internal link list on the heap or the stack? – user440297 May 18 '11 at 12:20
  • In the case of the list, as it needs to support adding an arbitrary number of elements, it's allocated on the heap. – Gabriel May 18 '11 at 16:05