【问题标题】:Returning static local variables as references返回静态局部变量作为引用
【发布时间】:2012-11-05 15:34:44
【问题描述】:

当作为引用返回并作为指针直接传递给另一个函数时,静态变量会发生什么?显然,该变量在函数返回后仍然存在,但是关于整个概念的某些事情让我感到困扰。数据序列上被静态变量占用的内存在哪一点被释放?当我不再需要它时,运行时是否会神奇地注意到它,比如某种垃圾收集?

举个例子:

SDL_Rect* XSDL_RectConstr(int x, int y, int w, int h)
{
    static SDL_Rect rect;
    rect.x = x;
    rect.y = y;
    rect.w = w;
    rect.h = h;

    return ▭
}

void mainLoop()
{
    while(isRunning)
    {
        pollEvents();
        SDL_BlitSurface(someSurface, XSDL_RectConstr(0, 0, 100, 100), screen, NULL);
        SDL_Flip(screen);
    }
}

SDL_BlitSurface() 返回后rect 会发生什么?我看不到它什么时候会被释放。这不会是某种内存泄漏吗?

【问题讨论】:

    标签: c++ memory-management static local


    【解决方案1】:

    此时数据序列上的内存被 静态变量,释放?当我没有时,运行时是否会神奇地注意到 不再需要它,比如某种垃圾收集?

    它会在程序退出时被释放,而不是更早。此外,它保证会调用析构函数。

    【讨论】:

    • 所以它仍然会占用大量内存,因为它在无限循环中运行,对吧?还是每次调用 XSDL_RectConstr() 时都会覆盖自己?此外,SDL_rect 是一个结构,而不是一个类,因此没有析构函数,但我想这无关紧要。
    • 它会覆盖自己,这就是问题所在。每个结构(和每个类)都有一个析构函数,如果你不写一个,就会生成一个默认的。
    • 它不会“覆盖”任何东西。这是同一个对象。这里唯一的魔力是它直到你第一次进入该函数时才被构造。除了通常的范围规则之外,这与在命名空间范围内定义的 static 没有什么不同。它就像函数的静态“成员”。
    • @LightnessRacesinOrbit 是的,所以第二次调用 XSDL_RectConstr 会覆盖第一次调用 XSDL_RectConstr 设置的值。
    • @john:对,那个,好的。但是“覆盖自身”是不正确的。函数中的以下几行?当然,他们正在为同一个原始对象的成员分配值。
    【解决方案2】:

    rect 在从SDL_BlitSurface 返回时不会被释放,但它也不会是内存泄漏:它在静态存储中,所以没有什么可以“泄漏”。只要您的程序正在运行,该对象就会一直保留在内存中。

    当您开始使用多线程时,最大的缺点会发生:您的静态变量存在被多个线程同时修改的风险,这是您宁愿避免的。

    Destructors for initialized objects of static storage duration (declared at block scope or at namespace scope) are called as a result of returning from main and as a result of calling exit.

    【讨论】:

    • 我可以通过在函数周围使用互斥锁来解决多线程问题,对吗?
    • @cyberpunk_ 是的,这是正确的。互斥体需要围绕函数调用,并包含使用静态变量中的值以及调用本身的代码。
    【解决方案3】:

    没有内存泄漏,但这是一个非常非常糟糕的主意。假设你写了一些这样的代码

    SDL_someFunction(
        XSDL_RectConstr(0, 0, 100, 100), 
        XSDL_RectConstr(20, 20, 30, 30)
    );
    

    因为你只有一个静态矩形,SDL_someFunction 不会得到它看起来会得到的不同矩形。相反,您将获得两次相同的矩形。

    【讨论】:

    • 所以我想如果我用它来确保我总是得到相同的数据,那没关系,对吧?
    猜你喜欢
    • 2022-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 2018-08-02
    相关资源
    最近更新 更多