C++;11核心语言处理单例死引用? 我最近读了Andrei Alexandrescu的现代C++设计。读完6。第二章,我开始担心我们公司的单身汉。由于我们经验丰富的团队领导编写了核心助手库,如Singleton等。我问他处理singleton的方式是否能解决死引用问题?如果他使用C核心语言给出的at_退出函数调用

C++;11核心语言处理单例死引用? 我最近读了Andrei Alexandrescu的现代C++设计。读完6。第二章,我开始担心我们公司的单身汉。由于我们经验丰富的团队领导编写了核心助手库,如Singleton等。我问他处理singleton的方式是否能解决死引用问题?如果他使用C核心语言给出的at_退出函数调用,c++,c++11,singleton,C++,C++11,Singleton,他告诉我,C++11支持单例,并将连续执行CTOR和DTOR,这不会造成任何死引用问题。用户不必处理同步 即使听起来很棒,我在网上也找不到任何证实他的信息。所以请告诉我C++11是否处理了单例的死引用问题,如果是这样,请解释一下背后的黑魔法是什么 您的团队负责人可能正在谈论按如下方式实施的单身人士: T &get_value() { static T val; return val; } 在这种情况下,标准给出了两种保证。第一个是val对象将只构造一次,即程序执行流第一次

他告诉我,C++11支持单例,并将连续执行CTOR和DTOR,这不会造成任何死引用问题。用户不必处理同步


即使听起来很棒,我在网上也找不到任何证实他的信息。所以请告诉我C++11是否处理了单例的死引用问题,如果是这样,请解释一下背后的黑魔法是什么

您的团队负责人可能正在谈论按如下方式实施的单身人士:

T &get_value() {
   static T val;
   return val; 
}
在这种情况下,标准给出了两种保证。第一个是
val
对象将只构造一次,即程序执行流第一次通过局部静态变量的声明,即使这在多个线程上同时发生
6.7/4

在与允许实现在命名空间范围(3.6.2)中静态初始化具有静态或线程存储持续时间的变量相同的条件下,允许实现执行具有静态或线程存储持续时间的其他块范围变量的早期初始化。否则,在控件第一次通过其声明时初始化该变量;此类变量在初始化完成时被视为已初始化。如果初始化通过抛出异常退出,则初始化未完成,因此下次控件进入声明时将再次尝试初始化。如果控件在初始化变量时并发输入声明,则并发执行应等待初始化完成

静态初始化只允许在常量的情况下进行,因此只要
T
没有
constexpr
构造函数,您就不必担心(但如果存在与代码相关的边缘情况,请阅读3.6.2了解完整规则)

第二个保证是,所有具有静态存储持续时间的变量将按照其构造的相反顺序被破坏
3.6.3/1

作为从main返回和调用std::exit(18.5)的结果,调用具有静态存储持续时间的初始化对象(即生命周期(3.8)已开始的对象)的析构函数(12.4)。在给定线程内具有线程存储持续时间的初始化对象的析构函数将作为从该线程的初始函数返回的结果以及该线程调用std::exit的结果而被调用。线程存储持续时间在该线程内的所有初始化对象的析构函数的完成顺序将在具有静态存储持续时间的任何对象的析构函数启动之前排序。如果一个具有线程存储持续时间的对象的构造函数或动态初始化的完成顺序先于另一个对象,则第二个对象的析构函数的完成顺序先于第一个对象的析构函数的启动顺序。如果具有静态存储持续时间的对象的构造函数或动态初始化的完成顺序先于另一个对象,则第二个对象的析构函数的完成顺序先于第一个对象的析构函数的启动顺序。[注意:此定义允许并发销毁。-结束注意]如果对象是静态初始化的,则该对象的销毁顺序与对象是动态初始化的顺序相同。对于数组或类类型的对象,在销毁在构造子对象期间初始化的具有静态存储持续时间的任何块作用域对象之前,将销毁该对象的所有子对象。如果通过异常退出对具有静态或线程存储持续时间的对象的销毁,则调用std::terminate(15.5.1)

当静态对象的构造是并发的时,这一段给出了并发破坏静态对象的很多范围,但要从中去掉的主要内容是,破坏是以与构造相反的顺序发生的


总的来说,这意味着如果
T val
依赖于这些单例函数中的另一个中的
U val
,那么
U val
将始终在
T val
之前构造,并在
T val
之后销毁,因此总体而言,这是实现单例的安全方法(除非你正在做一些非常疯狂的事情)。

你的团队负责人大概在谈论按如下方式实施的单身汉:

T &get_value() {
   static T val;
   return val; 
}
在这种情况下,标准给出了两个保证。第一个保证是
val
对象将被构造一次,即程序执行流第一次通过局部静态变量的声明时,即使这在多个线程上同时发生
6.7/4

在与允许实现在命名空间范围(3.6.2)中静态初始化具有静态或线程存储持续时间的变量相同的条件下,允许实现执行具有静态或线程存储持续时间的其他块范围变量的早期初始化。否则,当控件第一次通过其声明时,该变量将被初始化;初始化完成时,该变量将被视为已初始化。如果初始化通过引发异常退出,则初始化未完成,因此将在控件下次进入声明时重试。如果在初始化变量时,Control并发输入声明,并发执行