ChaoSXDemon
ChaoSXDemon

Reputation: 910

Polymorphic C++ with Pure Virtual Function destructor

I am not sure if the following code is safe from memory leak.

#ifndef RENDERABLE_H
#define RENDERABLE_H

class QGLShaderProgram;
class GLWidget;
class BoundingBox;

class Renderable{

public:
    virtual void update(float duration) = 0;
    virtual void render(QGLShaderProgram& shader, float duration) = 0;
    virtual BoundingBox* getBBox() const = 0;
    virtual void translate(float xx, float yy, float zz) = 0;
    virtual void rotate(float degrees_x, float degrees_y, float degrees_z) = 0;
    virtual void scale(float xx, float yy, float zz) = 0;
};

#endif // RENDERABLE_H

The above "interface" is been implemented by object3d.cpp. We may then add many Object3D objects into a Scene object if they belong to the same scene. However, upon the end of the scene, I want to ensure there is no memory leak and so I would call delete on everything. However, in the scene object, I have the following variable:

QVector<Renderable*>* sceneObjects;
QVector<GLTexture2D*>* sceneTextures;
QMap<QString, Material*>* sceneMaterials;

As you can see,

delete sceneObjects;
delete sceneTextures;
delete sceneMaterials;

should delete the QVector and according to Qt, it should call the destructor of those objects in it. However, Qt documentation were not clear about object POINTERS. Would Qt delete object pointers with their proper destructor? Additionally, what happens to Renderable pointers? As you can see from the "interface" that it has no destructor.

Thanks for any input. ChaoSXDemon

Upvotes: 1

Views: 380

Answers (2)

Nikos C.
Nikos C.

Reputation: 51920

You need to delete each pointer manually. You don't need to iterate over every one manually though. You can do this very easily with:

qDeleteAll(*sceneObjects);
delete sceneObjects;

Same for your other containers. qDeleteAll is documented here: http://doc.qt.digia.com/qt/qtalgorithms.html#qDeleteAll-2

Also add a virtual dtor, as Seth Carnegie mentioned.

Upvotes: 2

Seth Carnegie
Seth Carnegie

Reputation: 75150

First of all, your Renderable class must have a virtual destructor, because calling delete on a base pointer to a derived object is undefined behaviour without one.

Second, no, you will need to loop through and call delete on each pointer (or, as Nikos noted, use qDeleteAll as long as every object in the container is allocated with plain new (and not new[] or malloc or anything else)) in each container to make sure their memory is reclaimed (how could Qt know if the pointers point to things allocated by new? They could point to things allocated by new[], things on the heap, the stack, or somewhere else).

If you don't want to do that, you can store unique_ptrs in the containers and then the destructors of the unique_ptrs will be called when you delete the containers, and those destructors will deallocate the memory they own. No need to manually deallocate them or use qDeleteAll.

Upvotes: 5

Related Questions