在我的项目中,我正在与约4个单例一起完成Scott Meyer的设计。其中之一:

LevelRenderer& LevelRenderer::Instance()
{
    static LevelRenderer obj;
    return obj;
}

现在,这些单例中的两个LevelRendererLevelSymbolTable相互交互。例如,在这种方法中:
void LevelRenderer::Parse(std::vector<std::string>& lineSet)
{
    LevelSymbolTable& table = LevelSymbolTable::Instance();

    /** removed code which was irrelevant **/

    // for each line in lineSet
    BOOST_FOREACH(std::string line, lineSet)
    {
        // for each character in the line
        BOOST_FOREACH(char sym, line)
        {

            /** code... **/

            // otherwise
            else
            {
                sf::Sprite spr;

                // Used LevelSymbolTable's Instance here...
                table.GenerateSpriteFromSymbol(spr, sym);
                // ^ Inside LevelRenderer

                /** irrelevant code... **/
            }
        }
    }
}

现在,尽管问题尚未发生。我担心的是,如果在调用LevelSymbolTable之前GenerateSpriteFromSymbol实例已被销毁,该怎么办?

由于我使用了Scott Meyer方式,因此Singleton的实例由堆栈分配。因此,可以确保使用最后创建的第一个销毁规则销毁该销毁规则。现在,如果LevelSymbolTable的实例是在LevelRenderer的实例之后创建的,它将在LevelRenderer的实例之前被销毁,对吗?因此,如果我在LevelSymbolTable(特别是在LevelRenderer的析构函数中)中调用LevelRenderer的方法,我将踏上未定义的行为 Realm 。

就像我之前说过的那样,这个问题实际上不是在调试时发生的,而纯粹是我的假设和猜测。那么,我的结论正确吗? LevelSymbolTable易于在LevelRenderer之前销毁吗?如果是这样,有没有办法解决这个困惑局面?

最佳答案

您在这里不必担心任何事情。* static关键字保证从初始化到程序退出都可用。因此,您可以在初始化静态变量后随时对其进行调用。

另外,您引用的是LevelSymbolTable,而不是局部变量。这就是类名后面的“&”号的含义。因此,您可以在本地使用它,但这实际上是“引用”存在于其他地方的真实对象。因此,当方法退出时,引用将超出范围,但它所引用的对象则不会。

*好吧,您可能不得不担心一件事。在析构函数中,您应该清理所有内存或文件引用或其他您可以处理的东西。我不知道您为什么要在析构函数中调用其他对象。

09-07 08:28