1

我不确定以下代码是否可以避免内存泄漏。

#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

上面的“接口”是由object3d.cpp实现的。然后,如果它们属于同一个场景,我们可以将许多 Object3D 对象添加到一个场景对象中。但是,在场景结束时,我想确保没有内存泄漏,所以我会在所有内容上调用 delete。但是,在场景对象中,我有以下变量:

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

如你看到的,

delete sceneObjects;
delete sceneTextures;
delete sceneMaterials;

应该删除 QVector 并且根据 Qt,它应该调用其中那些对象的析构函数。然而,Qt 文档并不清楚对象指针。Qt 会使用适当的析构函数删除对象指针吗?此外,Renderable 指针会发生什么?从“接口”可以看出它没有析构函数。

感谢您的任何意见。ChaoSX恶魔

4

2 回答 2

5

首先,您的Renderable类必须有一个虚拟析构函数,因为调用delete指向派生对象的基指针是未定义的行为。

其次,不,您需要在每个容器中循环并调用delete每个指针(或者,正如 Nikos 指出的那样,qDeleteAll只要容器中的每个对象都分配有普通的new(而不是new[]malloc其他任何东西)),以确保它们的内存被回收(Qt 怎么知道指针是否指向由 分配的东西new?它们可以指向由 分配的new[]东西、堆上的东西、堆栈或其他地方)。

如果您不想这样做,您可以将unique_ptrs 存储在容器中,然后在容器unique_ptr中调用 s的析构函数delete,这些析构函数将释放它们拥有的内存。无需手动释放它们或使用qDeleteAll.

于 2012-10-25T21:48:29.130 回答
2

您需要手动删除每个指针。不过,您不需要手动迭代每一个。你可以很容易地做到这一点:

qDeleteAll(*sceneObjects);
delete sceneObjects;

其他容器也是如此。qDeleteAll记录在这里:http ://doc.qt.digia.com/qt/qtalgorithms.html#qDeleteAll-2

正如 Seth Carnegie 所提到的,还要添加一个虚拟 dtor。

于 2012-10-25T21:55:45.797 回答