引用单例是否在堆栈或堆上?

时间:2014-09-19 04:30:19

标签: c++ pointers reference singleton

我在这里读过很多关于单身人士的文章,但没有一篇真正触及我的问题。我知道Singletons应该只在需要时使用,在我的游戏中,我将它们用于引擎的特定部分。

那就是说,我最初把我的单身人士作为这样的指针:

static MapReader* Instance()
{
    if (instance == 0)
    {
        instance = new MapReader();
        return instance;
    }
    return instance;
}

然而,我总觉得使用太多指针对于泄漏是不好的,如果我可以帮助它,我宁愿不使用它们(如果必须的话,我更喜欢使用智能指针)。所以我把所有的单身人士改成了这样的参考文献:

static MapReader& Instance()
{
    static MapReader instance;
    return instance;
}

然而,现在我注意到我的游戏在奇数时间滞后然后加速,就像FPS有点不稳定。

我的问题是;引用单例是否堆积在堆栈上?还是他们仍然在堆上分配?我应该使用智能指针将它们更改回指针吗?

2 个答案:

答案 0 :(得分:3)

由于它不是用new创建的,所以几乎肯定不会在堆上。

但是,标准在上放置了 static个变量,只提及他们的行为。例如,见C++11 3.7.1:< / p>

  

1 /所有没有动态存储持续时间,没有线程存储持续时间且不是本地的变量都有静态存储持续时间。这些实体的存储应持续到程序的持续时间(3.6.2,3.6.3)。

     

2 /如果具有静态存储持续时间的变量具有初始化或具有副作用的析构函数,即使它看起来未被使用也不应被消除,除非类对象或其复制/移动可以按照12.8。

     

3 /关键字static可用于声明具有静态存储持续时间的局部变量。

     

4 /应用于类定义中的类数据成员的关键字static为数据成员提供静态存储持续时间。

这几乎就是标准本身对他们施加的程度。

大多数实现可能都有一个与堆和堆栈分开的区域,用于存储静态存储持续时间的变量。

几乎可以肯定的是,使用静态和引用会降低代码速度。深入研究编译器及其工作原理后,静态函数往往与其他变量一样快 ,因为它们很快就能在内存中找到。


顺便说一句,你的单例的指针变体有两个问题。如果您在线程环境中工作,首先是潜在的竞争条件。如果不同的线程调用Instance(),则可能会创建多个对象。

具体来说,如果线程A进入if语句,那么线程B开始运行,B可以通过,创建一个对象然后返回。如果A继续,则会创建对象。

如果您是单线程的,或者您只从一个线程创建实例,或者在其他线程运行之前创建实例,那么您应该没问题。

第二个问题只是眼睛糖果。没有必要从if块中返回对象,因为当你到达函数的底部时它将被返回:

static MapReader* Instance() {
    if (instance == 0)
        instance = new MapReader();
    return instance;
}

答案 1 :(得分:1)

都不是。函数内的静态变量驻留在数据部分中。对于记录,函数外部的静态变量和全局变量也是如此。