我试图实现以下行为(简化):
概念上是这样的:
class Object {
public:
//...
~Object() { reg.erase(this); }
static void register(Object* obj) { reg.insert(obj); }
static std::set<Object*> reg;
}
这是简化的,因为它不是真正的集合,而是更复杂的容器。因此,在register()和析构函数中涉及一些迭代器等。为简洁起见,我也省略了getter / setter和访问控制。
我遇到的问题是,只要没有人创建静态Object(或派生),它就能工作。然后它将取决于静态集和静态对象的实际破坏顺序(如果我没有弄错的话,这是不确定的)。我测试它真的崩溃与否,取决于这两个的顺序。我不能(并且不想)保证不会创建任何静态的Object实例。我也不想强制类的用户调用任何清理代码等。对象应该是&#34;自我意识&#34;。
我尝试使用单件装置,但是我继续用析构函数中的静力学回到同样的鸡和蛋问题。
如何修复此问题或使用其他设计实现相同的行为(可能没有那么多静态)?也许有一种方法可以确保特定静态在其他任何东西之后被销毁(至少在&#34;我的#34;代码中)?
答案 0 :(得分:1)
您是否可以强制该类用户对Object
的所有静态实例使用Construct On First Use Idiom?然后,它们应始终在应该在main
之前构造的容器之后构造。静态对象以与构造相反的顺序被破坏。因此,首先销毁容器之后构造的所有静态Object
。
引自标准§3.6.3/ 1:
...如果构造函数完成或者动态初始化一个具有静态存储的对象 持续时间在另一个持续时间之前排序,第二个析构函数的完成顺序排序 在第一个析构函数启动之前。
如果这是不可接受的,那么如何向Object
类添加标记:
class Object {
public:
bool registered; // init to false, set to true on registration
~Object() { if(registered) reg.erase(this); }
然后修改容器的析构函数(如果无法修改当前容器,则使用自定义委托容器或子类)在清除内容之前为每个指向对象设置标志false
。如果您将容器包装到带有自定义删除器的unique_ptr
中,也可以这样做。