【问题标题】:When is memory allotted to static variables in C++什么时候内存分配给 C++ 中的静态变量
【发布时间】:2011-03-17 06:33:06
【问题描述】:

我是 C++ 的新手,遇到了一个问题。

我在一本书中读到,一旦创建了该类的对象,就会将内存分配给静态变量。现在,如果我将这个静态变量设为全局怎么办?这种情况下什么时候初始化?

另外,我还在一些文章中读到静态变量分配在堆上并且它们不依赖于对象的构造......这是真的吗?如果是,请给我解释一下内存初始化步骤,我需要帮助。

非常感谢!

【问题讨论】:

    标签: c++ memory static initialization


    【解决方案1】:

    首先:停止思考 C 和 C++ 中的全局变量,否则您将永远处于混乱状态。这个问题比 Python 或 Pascal 等问题更复杂,因此您不能只使用一个词来表示概念。

    其次,没有“堆”或“栈”——这些是操作系统和 CPU 的细节,与抽象的 C++ 语言规范无关。

    现在,变量具有 1) 作用域、2) 链接和 3) 存储类。 static 关键字用于影响所有三个方面,具体取决于您使用它的位置。

    作用域:声明变量的位置。如果在函数内,则为函数作用域,如果在函数外,则为文件作用域(您可能将其称为“全局变量”)。

    链接:变量是否可以从其他编译单元访问(当您的程序包含多个源文件时相关)。

    存储类:

    静态变量在程序启动时以实现定义的方式分配,它们一直存在到程序结束。它们不能被“释放”或“重新分配”。 (典型的实现是其他人提到的 BSS 和 DATA 段)。

    自动变量只存在于函数范围内,它们在函数入口(通常在 CPU 的堆栈上)分配(并且可能初始化)并在函数退出时释放。

    动态 存储类可能是您所指的“堆”。这些是通过 malloc/free 或 new/delete 直接操作存储的变量。静态变量的存储与动态存储的管理方式非常不同,这两种存储从根本上是不兼容的。

    例子:

    ===
    // ALL file-scope variables have static storage class
    int global1;        // file-scope, external linkage
    static int global2; // file-scope, internal linkage
    
    void f()
    {
      static int x;     // static storage class, function-scope
      int y;            // automatic storage class, function-scope
    
      free(&x);         // ILLEGAL, WILL CRASH!
      free(&y);         // DITTO!
      free(&global1);   // DITTO!
    }
    ===
    

    现在,所有具有静态存储类(global1、global2 和 x)的变量都在程序启动之前分配和初始化。如果您不指定初始值,它们将在 UNSPECIFIED ORDER 中默认初始化。 (对于原始类型,这只是意味着用零填充)。

    静态变量仅在程序退出时被释放。这意味着,函数 f 中的“x”将仅初始化一次(在程序启动时),并且它将在函数调用之间保留其值(与将在每个函数条目上分配并在每个函数处释放的 y 不同)退出,因此它的价值也被破坏了)。请注意,在函数中使用静态变量与多线程和重入非常不兼容,除非您非常清楚自己在做什么。

    【讨论】:

    • 注意:并非完全未指定。同一编译单元中的所有文件范围变量都按照声明/定义的顺序进行初始化。只是没有指定跨编译单元的顺序是什么(或者即使不同编译单元中的文件范围变量在初始化期间交织在一起)。
    • 在上面的程序中:'global1'首先用0初始化。'global2'用0初始化。'x'在第一次调用函数f()时被初始化。
    • 我想在这里再补充一个疑问。静态函数的初始化和普通函数的初始化有什么区别?我已经读过,即使是普通函数也只有 1 个副本,无论对象的数量是多少 - 这与静态函数非常相似......
    • 'static' on functions 仅影响链接:该函数获得内部链接,并且只能从定义它的同一文件中访问。这使得在多个文件中定义一个名为“f”的静态函数成为可能。如果您尝试使用非静态函数执行此操作,链接器将抱怨符号 'f' 的多个定义。
    【解决方案2】:

    静态变量根本不存储在堆中。

    未初始化的静态变量存储在 BSS 段中。

    初始化的静态变量存储在数据段中。

    您可以阅读这篇文章,它以很好的方式解释了所有这些: http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory

    【讨论】:

    • 是存储全局变量的标准吗?如果是这样,我想从标准中获得参考。
    【解决方案3】:

    在程序启动时(在主程序之前)将为您的静态全局变量分配内存。

    我不知道第二个问题。

    【讨论】:

      猜你喜欢
      • 2015-09-15
      • 1970-01-01
      • 2019-07-12
      • 1970-01-01
      • 2011-10-28
      • 1970-01-01
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多