函数内部静态变量的内存分配

zak*_*ist 0 c++ memory static

static void func1(){
    static int i(9);
};
Run Code Online (Sandbox Code Playgroud)

是否在调用函数或程序启动时为静态变量 i 分配了内存?

pax*_*blo 6

对于这种特殊情况,这取决于实现。第一,分配问题。

确实,标准规定静态存储持续时间变量是作为程序启动的结果而初始化的。参见,例如C++17 [basic.static.start]

(1) 具有静态存储持续时间的变量作为程序启动的结果被初始化。

这似乎表明必须在main开始之前分配内存。但是,C++(如 C)也遵循“as-if”规则,该规则指出:

... 一个实现可以自由地忽略本国际标准的任何要求,只要结果就好像要求已被遵守,只要可以从程序的可观察行为中确定。

因此,由于i显然无法从您的函数外部访问,因此可以将变量的创建推迟到该点。实际上,因为即使在函数中i也从未使用过(并且因为它是具有简单构造函数或析构函数的基本类型),所以它实际上可以永远推迟并优化不存在:-)

接下来,初始化。上述标准链接区分了使用常量和非常量表达式的初始化。后者,动态初始化,需要在您第一次到达声明时完成,因为它可能取决于用于初始化它的其他程序变量的当前状态。

但是,由于您使用常量9来初始化您的整数(并且9在程序执行期间的任何时候都不会改变),这显然属于标准的常量初始化部分。在这种情况下,变量只需要在使用前就已经存在并初始化,因此可以在程序启动和初始声明之间的任何时候完成。

文中对此进行了说明:

(3) 允许实现将具有静态或线程存储持续时间的变量初始化为静态初始化,即使此类初始化不需要静态完成,前提是 (3.1) 初始化的动态版本不改变任何其他静态或线程存储持续时间对象在初始化之前的值;(3.2) 如果所有不需要静态初始化的变量都被动态初始化,则初始化的静态版本在初始化变量中产生的值与动态初始化产生的值相同。


底线可能是您应该少考虑实施的底层机制,而应专注于标准要求的内容。

在这种特殊情况下,分配和/或初始化发生main在第一次遇到声明之前或之后没有任何区别。一旦您开始使用非平凡的构造函数或析构函数,情况可能会有所不同,但在这种情况下则不然。