C++ - 非本地静态对象vs本地静态对象

问题描述:

关于来自Scot Meyers的书籍“Effective C++”,以及第4项:非本地静态对象可以在使用之前未初始化(在本例中静态意味着“全局“,静态的生活)。如果将其替换为在返回对其引用的函数内部创建的local-static对象,则该对象在使用前确定已初始化。C++ - 非本地静态对象vs本地静态对象

我总是有一个带有常量的文件。我在.hpp文件中声明extern const int a;并在.cpp文件中定义它。但是,那么同样的事情会发生吗? a可以是未初始化的。或不?相同的规则是否适用于内置类型?

+4

全局范围内的变量*始终*初始化。即使它们在定义时没有明确的初始化,系统也会[*初始化*](http://en.cppreference.com/w/cpp/language/zero_initialization)。无论如何,'const'变量必须被明确地初始化。 –

+0

你可能想看看http://*.com/questions/1005685/c-static-initialization-order –

+0

嘿家伙,谢谢你!据我所见,初始化内置类型的全局对象总是由编译器处理,不必介意它们是本地还是非本地... – Dusan

尽管可以,但返回对“local-static”变量的引用并不是一个好主意。这个变量(大概)是在本地声明的,以便将它的范围缩小到封闭函数,所以试图以这种方式增加它的范围是相当黑的。你可以使它成为一个全局变量,并使用类似std::call_once的内容来保证它在第一次使用时仅被初始化一次。将可变引用返回给本地静态对象也会引发线程安全问题,因为该函数可能不再可重入。

具有静态存储时间的POD类型保证被零初始化。你也可以用一个常量表达式来初始化它们,并且这个语言将保证它们在动态初始化发生之前被初始化。这里的a similar question可能会提供一些额外的见解。

关于静态初始化被称为static initialization order fiasco问题:

总之,假设您有两个静态对象x和y存在于 不同的源文件,说x.cpp和y.cpp的。进一步假设y对象的初始化(通常是y对象的构造函数) 在x对象上调用某种方法。

所以,如果你有另一个使用你的常量的翻译单元,你有一个很好的机会,你的程序将无法正常工作。有时它是文件链接在一起的顺序,有些平台甚至在文档中定义它(我认为Solaris是这里的一个例子)。

The problem also applies to builtin types such as int.从常见问题中的例子是:

#include <iostream> 
int f(); // forward declaration 
int g(); // forward declaration 
int x = f(); 
int y = g(); 
int f() 
{ 
    std::cout << "using 'y' (which is " << y << ")\n"; 
    return 3*y + 7; 
} 
int g() 
{ 
    std::cout << "initializing 'y'\n"; 
    return 5; 
} 

int main() { 
    std::cout << x << std::endl << y << std::endl; 
    return 0; 
} 

如果运行该例子中,输出是:

使用 'Y'(其为0) 初始化 'Y'

因此,y首先得到零初始化,然后发生常量初始化(?)。

的解决方案是 Construct On First Use Idiom

的构建在第一次使用成语的基本思想是包装一个函数内部 静态对象。

静态位置对象是在控制流首次到达其声明时构建的。