4

我一直在使用匿名命名空间来存储本地数据和函数,想知道数据何时初始化?是应用程序以与静态数据相同的方式启动还是依赖于编译器?例如:

// foo.cpp
#include "foo.h"

namespace {

const int SOME_VALUE = 42;

}

void foo::SomeFunc(int n)
{
    if (n == SOME_VALUE)
    {
        ...
    }
}

问题出在使一些代码线程安全。在上面的示例中,我需要确定SOME_VALUE在第一次调用 SomeFunc 之前已初始化。

4

4 回答 4

6

C++ 标准,3.6.2/1

零初始化和用常量表达式初始化统称为静态初始化;所有其他初始化都是动态初始化。使用常量表达式 (5.19) 初始化的具有静态存储持续时间的 POD 类型 (3.9) 的对象应在任何动态初始化发生之前进行初始化。在同一翻译单元的命名空间范围内定义的静态存储持续时间并动态初始化的对象应按照其定义在翻译单元中出现的顺序进行初始化。

这实际上意味着,即使另一个翻译单元从外部调用您的 SomeFunc 函数,您的 SOME_VALUE 常量也将始终正确初始化,因为它是使用常量表达式初始化的。

尽早(在 main 之前)调用函数的唯一方法是在使用动态初始化初始化对象时。但是到那时,根据标准报价,您的 POD 变量的初始化已经完成。

于 2008-12-01T15:19:53.613 回答
2

在这种特殊情况下(全局变量为 const),该变量在编译时被“初始化”。

SOME_VALUE 始终等于 42。

事实上,大多数(全部?)编译器实际上会像硬编码一样编译它:

void foo::SomeFunc(int n)
{
    if (n == 42)
    {
        ...
    }
}
于 2008-12-01T14:51:55.823 回答
1

命名空间与初始化时间无关。命名空间所做的只是更改属于它的名称。

于 2008-12-01T14:52:14.277 回答
0

有关您的实际问题的正确答案,请参阅 Mathieu 的答案。

但是请注意,匿名命名空间不会影响全局和/或静态对象生命周期的开始和结束。换句话说,你和使用普通的旧全局变量一样容易受到静态初始化顺序问题的影响。

该链接还提供了一些关于避免该问题的提示,在下一个主题中使用“首次使用时构建”。

于 2008-12-01T14:52:05.167 回答