【发布时间】:2012-07-07 13:20:18
【问题描述】:
在我的项目中,我使用了大约 4 个按照 Scott Meyer 的方式制作的单身人士。其中之一:
LevelRenderer& LevelRenderer::Instance()
{
static LevelRenderer obj;
return obj;
}
现在其中两个 Singleton,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 的实例是由堆栈分配的。因此,保证使用 last created first destroy 规则被销毁。现在,如果LevelSymbolTable 的实例在LevelRenderer 的实例之后创建,它会在LevelRenderer 的实例之前被销毁,对吧?那么,如果我在LevelRenderer 中调用LevelSymbolTable 的方法(尤其是在LevelRenderer 的析构函数中),我将踏上未定义的行为领域。
正如我之前所说,这个问题在调试时实际上并没有发生,纯粹是我的假设和猜测。那么,我的结论正确吗? LevelSymbolTable 是否会在 LevelRenderer 之前被销毁。如果是这样,有没有办法摆脱这种混乱?
【问题讨论】:
-
是什么让您认为静态变量可以在程序运行时被销毁?
-
@MrLister 如果
LevelRenderer在程序退出(即在其析构函数中)调用LevelSymbolTable并且LevelSymbolTable已经被销毁怎么办? -
好吧,说真的,你为什么要这么做?我的意思是,这可能发生的唯一一次是在程序停止运行之后(即在
main中的“返回”之后)并且系统正在进行清理。你真的想在析构函数中做GenerateSpriteFromSymbol之类的事情吗? -
那为什么不把保存磁盘文件的代码放到LevelSymbolTable的析构函数中呢?
-
@IntermediateHacker 你不能让
LevelSymbolTable成为LevelRenderer的成员吗?如果两个单例以这种方式相互依赖,有时定义它们之间的所有权关系可能是有意义的。
标签: c++ memory-management singleton stack destructor