引用单例是在堆栈还是堆上?

Ori*_*ria 6 c++ singleton pointers reference

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

也就是说,我最初将单例作为指针,如下所示:

static MapReader* Instance()
{
    if (instance == 0)
    {
        instance = new MapReader();
        return instance;
    }
    return instance;
}
Run Code Online (Sandbox Code Playgroud)

然而,我总觉得使用太多指针对泄漏不利,如果可以的话,我宁愿不使用它们(或者如果必须的话,使用智能指针)。所以我将所有单例更改为如下引用:

static MapReader& Instance()
{
    static MapReader instance;
    return instance;
}
Run Code Online (Sandbox Code Playgroud)

然而,现在我注意到我的游戏有时会滞后,然后又加速,就像 FPS 有点不稳定一样。

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

pax*_*blo 3

几乎可以肯定它不在堆上,因为它不是用new.

然而,该标准没有提及变量的放置位置,仅提及它们的 行为。例如,参见:staticC++11 3.7.1

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;
}
Run Code Online (Sandbox Code Playgroud)