C++中的静态全局变量

55

我想使用malloc方法创建一个整数数组。我希望这个数组是全局的,并且可以在我的程序的任何地方使用。我在头文件中放置了类似于以下代码的代码:

static int *pieces;

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

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

当我尝试在调用创建数组的函数后,在主函数中访问数组中的数字时,它会崩溃并显示pieces未初始化。但是在我的函数中,我可以创建它并且可以很好地操作其中的数字。我原本以为通过将pieces设置为静态变量,无论何时在任何地方更改(或设置)某些函数,那么这将影响该变量的任何使用。基本上我想说的是,为什么pieces在主函数中看起来未设置,即使我在一个已经调用的函数中设置了它?


13
为什么要在C++中使用malloc - Oliver Charlesworth
6
去掉“static”这个关键字,因为它会在每个文件中创建一个局部副本。 - Mike Dunlavey
3
“新的”。或者更好的,一个“std::vector”。 - Oliver Charlesworth
10
@Oli因为他想这么做,这并没有什么问题。请只回答问题。 - Owl
3
@owl - 澄清意图正是评论的目的。正如我四年前指出的那样,C++中有更好的选择。 - Oliver Charlesworth
显示剩余7条评论
4个回答

113

Static是一个具有多重含义的关键字,在这种情况下,它意味着非全局 (转述)。

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

要修复此问题的第一件事是删除关键字static。这将导致"多次定义"问题。要解决这个问题,您应该在.cpp文件中定义变量,并在头文件中extern声明。


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

您可以使用new int[128]()而不是冗长的malloc语法,这也会执行初始化。或者你可以选择简单的道路(那就是它存在的原因),使用std::vector


32

关键在于这个:

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”函数。但是,我没有添加“release”函数。
请注意,这都是C语言,而不是C++。如果您使用的是C ++,则应该使用new,或者更好的方法是使用vector
此外,在C ++中使用静态变量时,请注意:C++静态初始化顺序

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

An inline function or inline variable (since C++17) has the following properties:

1) There may be more than one definition of an inline function or variable (since C++17) in the program as long as each definition appears in a different translation unit and (for non-static inline functions and variables (since C++17)) all definitions are identical. For example, an inline function or an inline variable (since C++17) may be defined in a header file that is #include'd in multiple source files.

2) The definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed (not necessarily before the point of access).

3) An inline function or variable (since C++17) with external linkage (e.g. not declared static) has the following additional properties:

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;

内联固定了很多错误...如果没有这个命令,我什么也做不了。如果我包含一个“头保护”,它会出现错误;如果我使用“静态”,它会给出其他错误。我无法弄清楚如何在单独的头文件中添加全局变量,而我想将其添加到主cpp文件中。 - SSpoke

3

对于不同架构的高性能代码,您可能希望使用malloc-y分配而不是通用new。这是因为您可以将其包装在类似mymalloc()的东西中,然后使用特定于架构的函数,例如实现适当对齐以避免缓存未命中并执行硬件制造商(例如IBM(Bluegene)或Intel(MIC))提供的其他巧妙操作的函数。所有这些优化的分配例程都具有malloc类型框架。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接