删除存储为需要的静态局部变量的数组,以及如何?

时间:2010-09-11 00:25:18

标签: c++ opengl static local delete-operator

我有一些数组和需要删除的资源,这些变量的值在程序的整个生命周期中都保留,它们只在一个函数中使用,所以它自然适合静态变量:

void func() {
    static GLfloat arrs[4] = {1, 1, 1, 1};
    static GLUquadric* quad = gluNewQuadric(); // delete with gluDeleteQuadric(quad)
    //... other codes ... 
}

但是,如果我使用静态,我将无法删除这些资源,因为我无法从函数外部访问这些变量。我可以制作这些全局变量,但如果可能的话我想避免这种情况。

所以问题是:

  1. 是arrs []堆栈还是堆分配?那么,我需要删除它吗?
  2. 在GLUquadric的情况下,显然编译器不知道如何正确删除它,现在我已经使用了一个非常好用的RAII包装器类,但我在寻找是否有更简单的方法
  3. valgrind抱怨没有发布GLUquadric,我想我只是清理它而不是沉默valgrind,即使程序应该即将结束我将释放它们并且这些资源可能(?)释放时该计划结束。

7 个答案:

答案 0 :(得分:2)

  1. 无需删除arrs [],它未在堆上分配。它不在堆栈中,它位于某个地方的数据段中,也是静态程序数据的一部分,并且在进程执行时会消失。

  2. 在堆上但一般不用担心。这种在静态初始化期间分配堆的效果并不是很好,但是如果最终需要任何析构函数调用(除去外部资源等),它只会出现字节。

  3. 已编辑:我仍然担心该堆对象。特别是如果它来自一些图书馆;你永远不知道内部是什么,它可能已经锁定了一些硬件资源或类似的东西。你不能在这里用智能指针等做任何事情,但如果你真的需要这样分配,可能值得用atexit()函数或类似的方法注册释放。或者将整个事物放入带有析构函数的全局静态单例对象中。如果你知道对象只包含数据,你就不用担心了,即不要担心你的堆。

答案 1 :(得分:1)

根据你的描述,我假设这些静态声明是在使用它们的函数内部声明的。在这种情况下,您不需要删除它们。事实上,如果你愿意,你不能删除它们。如果静态数据不可用,函数将无法正常工作,则无法将其删除。它们不是堆栈变量,因为它们比函数的生命周期更长。

答案 2 :(得分:1)

使用自动ptr:

int myFunc()
{
    static GLfloat                   arrs[4] = {1, 1, 1, 1};
    static std::auto_ptr<GLUquadric> quad    = gluNewQuadric();

    // Do Stuff
}

静态变量在首次使用时初始化 然后在应用程序终止时销毁它。因为它是一个智能指针,它将删除指针。

  

1:arrs []是堆栈还是堆分配?那么,我需要删除吗?

都不是。
不,你不需要删除它 它具有静态存储持续时间,这意味着它将一直存在,直到主要出口然后被其他静态存储持续时间对象销毁(按照创建的相反顺序)。

  

2:对于GLUquadric,显然编译器不知道如何正确删除它,现在我已经使用了一个非常漂亮的RAII包装器类,但我在寻找是否有更简单的方法。 / p>

没有。只需使用标准版即可使其尽可能简单。

答案 3 :(得分:1)

由于您的“删除”功能是一个简单的单一参数功能,您可以直接将TR1(或加速)shared_ptr与自定义删除器一起使用。

void func()
{
    static std::tr1::shared_ptr<GLUQuadric> quad(gluNewQuadric(), gluDeleteQuadric);
    // ...
}

答案 4 :(得分:0)

基本规则是我们应该只删除我们分配的内容。如果我们使用new分配,请使用delete释放内存。如果我们使用new[]分配,请使用delete[]释放内存。

所以

Q1。不,不要删除。我们从来没有新过它

Q2。是的,我们需要删除假设函数分配它。然而问题是,通过查看Quadratic,很难知道返回的指针是仅针对一个'Quadtric'还是'Quadtric'数组新建的,或者它只是指向某个静态变量的指针。因此,如果您动态分配了内存,请相应地使用deletedelete[]

答案 5 :(得分:0)

至于好奇和未来的参考,这是我的RAII模板:

template <typename T, T* constructor(), void destructor(T*)>
class Managed {
    private:
        T* value;
    public:
        Managed() {
            value = constructor();
        }
        ~Managed() {
            destructor(value);
        }
        T* operator*() {
            return value;
        }
};

它的用法如下:

typedef Managed<GLUquadric, gluNewQuadric, gluDeleteQuadric> MGLUquadric;
static MGLUquadric quad = MGLUquadric();
gluSphere(*quad, 3.0f, 20, 20);

答案 6 :(得分:0)

Q1和Q2:不要这样做!。您不能使用std::auto_ptr<GLUquadricObj>,因为它是需要由专门的删除器gluDeleteQuadric释放的资源。通常,在像OpenGL和GLU这样的状态驱动引擎中不使用静态 - 不要使用它们,但在OpenGL环境中,这是特别危险的。

再次,严肃地说:

Q1。不要这样做。存储静态4元素整数数组时根本没有任何增益。在您需要的地方定义它。我的建议:不要使用c风格的数组,而是说:

const std::array<int, 4> tArray = {1, 1, 1, 1};

Q2。上面给出的RAII建议很好,但是你需要一个支持自定义删除器的RAII包装器:

std::shared_ptr<GLUquadricObj> 
 tMyQuadric(glCreateQuadric(), glDeleteQuadric);

现在随意使用它,当它们超出范围并且程序没有引用它时,它将被自动关闭和销毁。哦,我看到上面的自定义RAII包装器也可以工作,但请:自己和你的追随者和同事一个忙:使用标准的库构造。