首页 > 解决方案 > 函数内部静态变量的内存分配

问题描述

static void func1(){
    static int i(9);
};

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

标签: c++memorystatic

解决方案


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

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

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

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

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

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

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

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

这被文本覆盖:

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


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

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


推荐阅读