2016-08-24 222 views
1

迈耶斯单身人士取决于local static variable initialization is atomic这一事实。C++是静态变量初始化= atomic?

我正在构建类似的东西,但我希望单例实际上是一些派生类型之一。基类getInstance()方法应调用将返回适当类型的工厂。

我的第一个想法是

static Foo *instance = FooFactory(...); 

N3337 8.5p2似乎表明,这是严格的初始化和未初始化和赋值,我理解这意味着整个语句是原子。它是否正确?

如果不将声明

static Foo *instance(FooFactory(...)); 

有所不同呢?

编辑8.5.2 - > 8.5.p2

回答

1

8.5.2是“[dcl.init.string]”,似乎并不相关。我认为你的意思是8.5分。

是的,这是严格的初始化(具体是复制初始化 - 见8.5段落14)。

如果声明在函数内部,那么,如the answer to the linked question shows,一切正常。

但是,如果这是名称空间范围内的静态变量,那么我看不到任何需要初始化的内容才是线程安全的。 (这只是一个问题,如果初始化创建线程 - 但我敢打赌它的确如此。)

+0

如果我看到一个创建线程的静态初始化,我会立即提出关于开发人员的管理问题:) – SergeyA

+0

特别令人兴奋的是,如果我们正在讨论一个Windows DLL - 在DllMain里面几乎什么都做(这是什么静态init)会导致静态加载器锁死锁:-) –

1

由于C++ 11,静态变量,是本地功能的初始化是原子和线程安全的,所以是的,你行的代码是线程安全的,实际上等同。 (语法明智的你的第一个版本调用复制构造函数,但没有编译器会生成它)。

但是,目前尚不清楚哪些参数将提供给您的Factory函数,以及哪些参数将从哪里获取?

+0

你能引用章节和诗句来初始化静态变量在*命名空间作用域*是线程安全的吗? §6.7[stmt.dcl] p4:表示“声明语句”是线程安全的,但我认为这只适用于块范围的声明。 (换句话说,函数内的静态声明)。要清楚 - 如果可以的话,这将很好。 –

+0

@MartinBonner,从来不想说任何关于命名空间范围的东西。问题的上下文当然是关于函数范围的静态的。将澄清是100%清楚。 – SergeyA

+0

我没有看到这个问题,但重新阅读,我认为你是对的。尽管如此,对于其他人在晚些时候通过谷歌发现这个问题的一个重要警告。 –

1

variable_type variable_name = initializer始终是初始化,而不是默认构造和分配。 [dcl.init]/15具有

发生在形式

T x = a; 

以及在元传递,函数返回,抛出异常(15.1),处理异常初始化(15.3 ),并且聚合成员初始化(8.5.1)被称为复制初始化。 [注意:复制初始化可以调用一个移动(12.8)。 - 注意]