【问题标题】:Static global variables in C++C++中的静态全局变量
【发布时间】:2013-01-16 01:08:58
【问题描述】:

我想通过 malloc 方法创建一个整数数组。我希望这个数组是全局的,可以在我的程序中的任何地方使用。我将代码放在如下所示的头文件中:

static int *pieces;

然后我有一个函数,用我想要的数字填充它。该函数位于命名空间中,并且命名空间在其自己的 .cpp 文件中实现。但是,我将头文件导入 main.c 并从创建数组的命名空间调用函数,如:

pieces = malloc(sizeof(int) * 128);

但是当我尝试在 main 中访问数组中的数字时(在调用创建我的数组的函数之后),它崩溃并说片段未初始化。但是在我拥有的函数中,我可以创建它并很好地操纵其中的数字。我的印象是,通过使片段成为静态变量,只要任何地方的某个函数发生更改(或设置它),就会影响任何地方的变量的使用。基本上我想说的是,为什么片段在 main 中出现未设置,即使我将它设置在我调用的函数中?

【问题讨论】:

  • 为什么要在 C++ 中使用malloc
  • 删除static这个词,因为这会在每个文件中创建一个本地副本。
  • @ChristianDaley:new。或者更好的是,std::vector
  • @Oli,因为他也想要。他的所作所为并没有错。请回答问题。
  • @owl - 明确意图正是 cmets 的目的。正如我四年前指出的那样,C++ 中有很多更好的选择。

标签: c++ variables pointers static global


【解决方案1】:

Static 是一个具有多种含义的关键字,在这种特殊情况下,它表示不是全局(释义)

这意味着每个.cpp文件都有自己的变量副本。因此,当您在main.cpp 中初始化时,它仅在main.cpp 中初始化。其他文件仍未初始化。

解决此问题的第一件事是删除关键字static。这将导致“多重定义问题”。要解决这个问题,您应该在 .cpp 文件中定义变量,然后在头文件中进行 extern 声明。


编辑:您只是为其分配内存,不算作初始化。分配后需要将内存初始化为0。

您可以使用new int[128]() 代替更冗长的malloc 语法,这也可以使用perform initialization?或者你可以走简单的路(这就是它的用途)并使用std::vector

【讨论】:

    【解决方案2】:

    关键是这个:

    static int *pieces;
    

    你说你把它放在你的标题中。这不是导出符号的方法。任何包含标头的文件都将获得一个名为pieces 的未初始化指针的静态版本。

    相反,你把它放在你的标题中:

    extern int *pieces;
    
    extern int init_pieces();
    

    在源文件中,你这样做:

    static const size_t num_pieces = 128;
    
    int *pieces = 0;
    
    int init_pieces()
    {
        pieces = malloc( num_pieces * sizeof(int) );
        return pieces != NULL;
    }
    

    现在,当您包含标题时,您的源文件将知道从其他地方获取pieces,并等待链接器确定在哪里。我还为数组建议了一个“init”函数。但是,我没有添加“释放”功能。

    请注意,这都是 C,而不是 C++。如果你使用 C++,你应该使用new 或者更好,使用vector

    另外,在 C++ 中使用静态时,请注意:C++ static initialization order

    【讨论】:

      【解决方案3】:

      在 C++17 标准中,您可以使用 inline 说明符代替静态。对于变量,这意味着每个对象单元都会有一个变量的副本,但链接器只会选择其中一个。 或者,如cppreference 所述:

      内联函数或内联变量(C++17 起)具有以下内容 属性:

      1) 内联可能有多个定义 程序中的函数或变量 (C++17 起),只要每个 定义出现在不同的翻译单元中并且(对于非静态 内联函数和变量 (C++17 起)) 所有定义都是 完全相同的。例如,内联函数或内联变量 (C++17 起) 可以在#include'd 的头文件中定义 多个源文件。

      2) 内联函数的定义或 变量 (C++17 起) 必须出现在翻译单元中 它被访问(不一定在访问点之前)。

      3) 具有外部链接的内联函数或变量(C++17 起)(例如 未声明为静态)具有以下附加属性:

      1) It must be declared inline in every translation unit.
      
      2) It has the same address in every translation unit.
      

      在 (source) 中支持:

      • MSVC 自版本 19.12 (VS 2017 15.5)
      • GCC 7
      • Clang 3.9
      • ICC 18.0

      在这种情况下,这意味着你可以替换

      static int *pieces;
      

      inline int *pieces;
      

      【讨论】:

      • inline 修复了太多错误.. 没有这个命令我什么都做不了,如果我包含 header guard 它会出错,如果我使用 static 它会给出其他错误我不能'不知道如何在单独的头文件中添加全局变量,我想将其添加到主 cpp 文件中。
      【解决方案4】:

      对于各种架构上的高性能代码,您可能需要 malloc-y 分配而不是通用 new。那是因为你会用 mymalloc() 之类的东西来包装它,然后使用依赖于架构的函数,例如那些实现正确对齐以避免缓存未命中的函数,以及执行硬件制造商提供的其他漂亮事情,例如 IBM (Bluegene) 或英特尔(MIC)。所有这些优化的分配例程都有 malloc 类型框架。

      【讨论】:

        猜你喜欢
        • 2015-06-12
        • 2012-12-30
        • 2015-10-04
        • 1970-01-01
        • 2018-12-22
        • 1970-01-01
        • 2011-04-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多