我最近读过Alexandrescu的“现代C++设计”。读完第六章后,我开始担心我们公司的单身人士。因为我们有经验的团队领导写核心助手库,比如单身汉.。我问他,他处理独生子女的方式是否解决了死掉的引用问题?如果他使用的是C核心语言给出的at_exit函数调用?
他告诉我,C++11有单例支持,并将连续执行CTORs和DTOR,它们不会成为任何死引用问题。用户将不必处理同步问题。
即使这听起来很棒,但我在网上找不到证实他的任何信息。所以,请告诉我,如果C++11处理单身人士的死亡参考问题,如果是的话,请解释一下背后是什么黑暗魔法?
发布于 2014-05-24 07:47:51
想必,您的团队组长正在谈论单身者,其实现方式如下:
T &get_value() {
static T val;
return val;
}在这种情况下,标准提供了两个保证。第一种情况是,val对象将精确构造一次,这是程序执行流第一次传递本地静态变量的声明,即使这在多个线程6.7/4上同时发生。
在允许实现静态初始化名称空间范围内静态或线程存储持续时间的变量(3.6.2)的相同条件下,允许实现对具有静态或线程存储持续时间的其他块范围变量执行早期初始化。否则,此类变量将在控件第一次通过其声明时被初始化;该变量在初始化完成后被视为初始化。如果通过抛出异常退出初始化,则初始化不完成,因此下次控件输入声明时将再次尝试初始化。如果在初始化变量时控件同时输入声明,则并发执行应等待初始化完成。
静态初始化只允许在常量的情况下进行,因此只要T没有constexpr构造函数,您就不必担心(如果有与代码相关的边缘情况,请阅读3.6.2获取完整规则)。
第二个保证是,所有具有静态存储时间的变量都将按构造3.6.3/1的相反顺序销毁。
对于已初始化对象(即其生存期(3.8)已开始的对象)的析构函数(12.4),由于从main返回并调用std::exit (18.5),将调用静态存储持续时间。在给定线程内具有线程存储时间的初始化对象的析构函数是从该线程的初始函数返回的结果,以及该线程调用std::exit的结果。在启动任何具有静态存储持续时间的对象的析构函数之前,将对该线程内具有线程存储持续时间的所有初始化对象的析构函数的完成进行排序。如果构造函数的完成或具有线程存储持续时间的对象的动态初始化在另一个对象的顺序之前被排序,则在启动第一个析构函数之前对第二个析构函数的完成进行排序。如果构造函数的完成或具有静态存储持续时间的对象的动态初始化在另一个对象的顺序之前被排序,则在启动第一个析构函数之前对第二个析构函数的完成进行排序。注:这一定义允许同时销毁。-尾注如果一个对象是静态初始化的,则该对象按相同的顺序销毁,就好像该对象是动态初始化的一样。对于数组或类类型的对象,在子对象的构造过程中初始化静态存储时间的任何块作用域对象被销毁之前,该对象的所有子对象都被销毁。如果具有静态或线程存储持续时间的对象通过异常退出,则调用std::终止(15.5.1)。
当静态物体的构造是同时进行的时候,这一段给出了对静态物体进行并行破坏的很大的空间,但最重要的是破坏是以相反的顺序发生的。
总之,这意味着如果T val依赖于另一个单例函数中的某些U val,那么U val总是在T val之前构建,在T val之后被破坏,所以总的来说,这是实现单例的一种安全方法(除非您正在做一些非常疯狂的事情)。
https://stackoverflow.com/questions/23842433
复制相似问题