可以在析构函数中访问静态成员的静态对象

时间:2014-03-18 10:36:45

标签: c++

我试图实现以下行为(简化):

  • 这是一个任何人都可以派生出来的Object基类,并且会有几个这样的实例。
  • 任何地方的任何人都可以添加一个实例指针,指向一组全局可访问的Object指针。
  • 一个对象应该在销毁时从该集合中移除(如果它在其中)。
  • 我只需要它在单个线程和单个模块中工作(没有动态库加载等)。

概念上是这样的:

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;代码中)?

1 个答案:

答案 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中,也可以这样做。

相关问题