我一直在使用匿名命名空间来存储本地数据和函数,并想知道数据何时被初始化?是应用程序以与静态数据相同的方式启动还是依赖于编译器?例如:
// foo.cpp
#include "foo.h"
namespace {
const int SOME_VALUE = 42;
}
void foo::SomeFunc(int n)
{
if (n == SOME_VALUE)
{
...
}
}
问题产生于使一些代码线程安全。在上面的例子中,我需要确保在第一次调用SomeFunc之前初始化SOME_VALUE
。
答案 0 :(得分:6)
C ++标准, 3.6.2 / 1 :
零初始化和 用常量初始化 表达被统称为 静态初始化;所有其他 初始化是动态的 初始化。 POD类型的对象 (3.9)具有静态存储持续时间 用常量表达式初始化 (5.19)应在任何之前初始化 动态初始化发生。 对象具有静态存储持续时间 在命名空间作用域中定义的相同 翻译单位和动态 初始化应初始化 他们定义的顺序 出现在翻译单元中。
这实际上意味着,即使另一个翻译单元从外部调用SomeFunc函数,您的SOME_VALUE常量也将始终正确初始化,因为它是用常量表达式初始化的。
早期调用函数(在main之前)的唯一方法是使用动态初始化初始化对象。但到那时,根据标准报价,POD变量的初始化已经完成。
答案 1 :(得分:2)
在这种特殊情况下(一个const的全局变量),变量在编译时被“初始化”。
SOME_VALUE总是等于42。
事实上,大多数(所有?)编译器实际上都会编译它,好像它是硬编码的一样:
void foo::SomeFunc(int n)
{
if (n == 42)
{
...
}
}
答案 2 :(得分:1)
命名空间与初始化时间无关。命名空间所做的就是更改属于它的名称。
答案 3 :(得分:0)
对于您实际问题的正确答案,请参阅Mathieu的回答。
但请注意,匿名命名空间不会影响全局和/或静态对象生命周期的开始和结束。换句话说,你就像使用简单的旧全局变量一样容易受到static initialization order问题的影响。
该链接还提供了一些避免问题的提示,使用“首次使用时构建”,在下一个主题中。