C++中的静态全局变量
Posted
技术标签:
【中文标题】C++中的静态全局变量【英文标题】:Static global variables in 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++ 中有很多更好的选择。
【参考方案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 类型框架。
【讨论】:
以上是关于C++中的静态全局变量的主要内容,如果未能解决你的问题,请参考以下文章