PDA

View Full Version : Memory management questions (im new to Qt)



scarvenger
6th May 2007, 05:38
Hi friends,

--Qt Questions

I'm currently starting Qt programming and i have some questions:



class Foo
{
...
static QList<Area*> *areas;
QList<Camera*> cameras;
...
}


{Considerations-> Camera and Area are normal classes, no Qt involved.}

1)I have these two objects, should i (in the destructor) call delete or delete [] for them?

2)Should i call delete for each Camera* and Area* object?

3)What would change in the first and in the second answer if the Foo class was derivated from QObject?

--Non-Qt questions

These are questions that always haunted me and never got answered:

1)What's the big catch in using pointers, i know some cases that pointers are good (like when we want to point something :p ) but when there's the option of choosing between pointer or non-pointer what parameters should I obey to choose one of them? Like:


class Foo
{
Foo(){};
~Foo(){};

void callMe() { cout<<"im alive"; };
}

void main()
{
Foo *f = new Foo(); //what are the advantages/disadivantages of using a pointer here instead of Foo f();
f->callMe();
delete f;
return;
}


2)

class Foo
{
Foo(){};
~Foo(){};
}

void main()
{
Foo f();
Foo *p_f = &f;
delete p_f; //does 'f' gets deleted here or can i continue using it?

createFoo(p_f);
//is p_f still valid here? i mean, wasn't the object f destroyed after leaving createFoo function?
return;
}

void createFoo(Foo* p_f)
{
Foo f();
p_f = &f;
}


Thank you!

wysota
6th May 2007, 07:26
1)I have these two objects, should i (in the destructor) call delete or delete [] for them?
Neither. Call qDeleteAll(*areas), qDeleteAll(cameras) and delete areas.


2)Should i call delete for each Camera* and Area* object?
Yes. That's what qDeleteAll does.


3)What would change in the first and in the second answer if the Foo class was derivated from QObject?
Nothing.


1)What's the big catch in using pointers, i know some cases that pointers are good (like when we want to point something :p ) but when there's the option of choosing between pointer or non-pointer what parameters should I obey to choose one of them?
There is no easy answer to that question. In general if you have a big stack, you should avoid pointers if you can. But sometimes you just have to use pointers (like with Qt widgets).


Like:


class Foo
{
Foo(){};
~Foo(){};

void callMe() { cout<<"im alive"; };
}

void main()
{
Foo *f = new Foo(); //what are the advantages/disadivantages of using a pointer here instead of Foo f();
f->callMe();
delete f;
return;
}

There are no disadvantages (apart from a slight overhead of the need to actually allocate the memory) and no advantages here.


2)

class Foo
{
Foo(){};
~Foo(){};
}

void main()
{
Foo f();
Foo *p_f = &f;
delete p_f; //does 'f' gets deleted here or can i continue using it?


This will segfault - you're deleting the object twice - first by explicitely calling delete and then when main() returns the compiler will try to delete the object again.



createFoo(p_f);
//is p_f still valid here? i mean, wasn't the object f destroyed after leaving createFoo function?
return;
}
No, it's not valid.

marcel
6th May 2007, 07:41
Firsts of all,It has been said before in other posts - Qt is not a garbage collector ( it is C++ after all ), so it only takes care of certain objects to be deleted. A QObject normally deletes all it's children.

Second of all, you should take a C++ book ( doesn't matter which one at this point ), and read it very carefully, cover to cover. You can try this link:
http://www.qtcentre.org/forum/f-general-programming-9/t-what-are-your-favourite-c-books-29.html

Anyway, here are you answers:

1. The destructor of your class should be:


Foo::~Foo()
{
if( cameras )
{
while( cameras->count() )
{
Camera* c = cameras->takeAt(0);
delete c;
}
}
delete cameras;
cameras = NULL;
}

Since the other QList is static, you can't delete it in the destructor, because other class instances can still exists and be using it. So you should have a static member that disposes the list at the end of your app:


void Foo::DisposeAreas()
{
if( areas )
{
while( areas->count() )
{
Area* a = areas->takeAt(0);
delete a;
}
}
delete areas;
areas = NULL;
}


delete[] is normally used for array allocated on the heap.
Something like:


Foo *fooArray = new Foo()[20];
...
delete[] fooArray;
This will cause 20 Foo destructors to be called.

2. Yes.

3. If the parent of the objects inside a QList is the QList itself, then the QObjects inside will be deleted, otherwise no.
This is because:


QObject::~QObject()
Destroys the object, deleting all its child objects. All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue. However, it is often safer to use deleteLater (http://www.qtcentre.org/forum/qobject.html#deleteLater)() rather than deleting a QObject (http://www.qtcentre.org/forum/qobject.html) subclass directly.
Warning: All child objects are deleted. If any of these objects are on the stack or global, sooner or later your program will crash. We do not recommend holding pointers to child objects from outside the parent. If you still do, the destroyed (http://www.qtcentre.org/forum/qobject.html#destroyed)() signal gives you an opportunity to detect when an object is destroyed.
Warning: Deleting a QObject (http://www.qtcentre.org/forum/qobject.html) while pending events are waiting to be delivered can cause a crash. You must not delete the QObject (http://www.qtcentre.org/forum/qobject.html) directly if it exists in a different thread than the one currently executing. Use deleteLater (http://www.qtcentre.org/forum/qobject.html#deleteLater)() instead, which will cause the event loop to delete the object after all pending events have been delivered to it.


--Non-Qt questions

1. No advantage or disadvantage ( as I said, read a good book with good examples ).

2. Lines 9-11.
That will not work and it will crash a program .You cannot delete p_f because it points to something allocated on the stack, and not in the heap.

Anyway, let's assume you did this:


Foo f();
Foo *p_f = new Foo();
delete p_f; //does 'f' gets deleted here or can i continue using it?

In this case p_f gets deleted and remains an invalid pointer ( points to an invalid memory location ). Therefore, no matter for what you are using it next, it has to be allocated, or you will get a mem violation.

Another error in the function createFoo().
Even if you reallocate p_f above, Foo f is local in createFoo, therefore it will be deleted when the function exits its scope( returns) - you can test this by adding a breakpoint in ~Foo right before this function returns. Therefore p_f will remain allocated but will contain an invalid object.
Actually here is a good example of why you should use a pointer - because a pointer is allocated on the heap, not on the stack, and it only gets deallocated by delete, it does not depend by the scope in which it was allocated



void createFoo(Foo* p_f)
{
Foo *f = new Foo();

if( p_f ) // do this, or don't allocate p_f again after deleting it, in main
{
delete p_f;
p_f = NULL;
}

p_f = f;
}

Hope this helps.

Regards