【问题标题】:How to enforce calling order of destructors如何强制执行析构函数的调用顺序
【发布时间】:2012-05-26 21:49:44
【问题描述】:

我正在尝试正确设置以下设置:

给定的应用程序(具有多个源文件、编译单元)在许多编译单元中定义了 class A 类型的全局变量。 这些应该由引入 class B 的新成员“管理”(其中应该只存在一个实例),因为在创建时它们在 B 类的实例中“注册”自己并在销毁时“注销”。

为构造函数设置工作是相当简单的。可以使用:

types.h:

class B {
  static B& Instance() {
    static B singleton;
    return singleton;
  }
  void registerA( const A& a ) { 
  // whatever
  }
};


class A {
  A() { B::Instance().registerA( this ); }
};

如何正确使用析构函数?如果使用:

class A {
  A() { B::Instance().registerA( this ); }
  ~A() { B::Instance().signoffA( this ); }
};

那么B 的析构函数可能会在A 的析构函数之前被调用。 然后A 类的实例在刚刚创建的B 实例上签名。

测试用例将是一个多源文件设置,在命名空间中定义了 class A 的实例:

file1.cc

#include "types.h"
namespace C {
   A a;
}

file2.cc

#include "types.h"
namespace C {
   A b;
}

我猜想使用 Boost 智能指针可以轻松完成这样的事情。但是,如果可能的话,我想避免使用额外的库来尽可能降低依赖性。

一件事可能会有所帮助:所有全局变量都在命名空间中。

【问题讨论】:

  • 请修正缩进和范围。
  • 另外,请考虑创建一个简短的连贯测试用例来说明您的 A 实例相对于其他所有内容的创建位置。目前有点混乱。
  • 请注意,register 是 C++ 和 C 中的关键字,因此您的代码无法编译。

标签: c++ constructor destructor


【解决方案1】:

我觉得你很好。这里是关于“终止”的 3.6.3:

如果具有静态存储持续时间的对象的构造函数或动态初始化的完成顺序在另一个之前,则第二个的析构函数的完成顺序在第一个的析构函数的启动之前。

假设您有以下设置:

struct A;

struct B
{
    static B & get() { static B impl; return impl; }
    void registrate(A *);

private:
    B() { /* complex stuff */ }
    // ...
};

struct A { A() { B::get().registrate(this); } };

A a1;

现在不管发生什么,静态A-type 对象的第一个构造函数将调用B::get(),它在第一个A-constructor 完成之前对静态impl 对象的构造进行排序。通过上述子句,这保证了B impl-object 的析构函数在所有A-destructors 之后排序。

【讨论】:

  • 引用的语句不是指两个对象都是静态存储持续时间的情况吗?就我而言,其中之一是static
  • 我不明白:..“静态 A 类型的第一个构造函数”。 A 不是静态的。
  • @Frank:“静态”并不代表你的想法。示例中的所有内容都有静态存储持续时间。关键字static 只是制作具有静态存储持续时间的对象的众多方法之一。
  • 哦,好的。全局变量的默认存储持续时间为static 持续时间。这就是该声明适用于此的原因。
  • @Frank:不是“默认”。简单的“是”。全局变量的存储时长是'静态'。
【解决方案2】:

B 实例是静态的,因此它会比在创建 B 单例后创建的任何 A 实例寿命更长。

【讨论】:

  • 如果所有对象都在同一个编译单元中,这肯定是正确的。这不是这里的情况。我不确定static 对象销毁是否也跨编译单元延迟
  • @Frank 我看不出它如何不适用于编译单元。
  • 是的,设置没问题。但原因是调用构造函数的顺序和它的静态事实。如果你同时指这两种情况,你是对的
猜你喜欢
  • 2015-08-02
  • 2017-06-13
  • 2016-04-20
  • 2012-06-08
  • 2010-12-23
  • 2015-05-14
  • 2018-05-08
  • 1970-01-01
  • 2013-06-24
相关资源
最近更新 更多