在我的项目中,我正在与约4个单例一起完成Scott Meyer的设计。其中之一:
LevelRenderer& LevelRenderer::Instance()
{
static LevelRenderer obj;
return obj;
}
现在,这些单例中的两个
LevelRenderer
和LevelSymbolTable
相互交互。例如,在这种方法中: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,而不是局部变量。这就是类名后面的“&”号的含义。因此,您可以在本地使用它,但这实际上是“引用”存在于其他地方的真实对象。因此,当方法退出时,引用将超出范围,但它所引用的对象则不会。
*好吧,您可能不得不担心一件事。在析构函数中,您应该清理所有内存或文件引用或其他您可以处理的东西。我不知道您为什么要在析构函数中调用其他对象。