C++中的静态全局变量

Chr*_*ley 35 c++ variables static pointers global

我想通过malloc方法创建一个整数数组.我希望这个数组是全局的,可以在我的程序中的任何地方使用.我把代码放在一个看起来像这样的头文件中:

static int *pieces;
Run Code Online (Sandbox Code Playgroud)

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

pieces = malloc(sizeof(int) * 128);
Run Code Online (Sandbox Code Playgroud)

但是当我尝试访问main中的数组中的数字时(在调用创建我的数组的函数之后),它崩溃并说没有初始化那些碎片.但是在我拥有的功能中,我可以创建它并操纵它中的数字就好了.我的印象是,通过使片段成为静态变量,只要某个函数在任何地方发生变化(或设置它),那么这将影响变量在任何地方的使用.基本上我想说的是为什么片断在主体中显示未设置,即使我将它设置在我调用的函数中?

Kar*_*k T 63

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

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

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


编辑:你只是为它分配内存,不算作初始化.分配后需要将内存初始化为0.

您可以使用new int[128]()而不是更详细的malloc语法,这也会执行初始化?或者你可以采取简单的道路(这就是它的用途)和使用std::vector


pad*_*ddy 17

关键是:

static int *pieces;
Run Code Online (Sandbox Code Playgroud)

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

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

extern int *pieces;

extern int init_pieces();
Run Code Online (Sandbox Code Playgroud)

在源文件中,您执行此操作:

static const size_t num_pieces = 128;

int *pieces = 0;

int init_pieces()
{
    pieces = malloc( num_pieces * sizeof(int) );
    return pieces != NULL;
}
Run Code Online (Sandbox Code Playgroud)

现在,当您包含标头时,您的源文件将知道pieces从其他位置获取,并将等待链接器计算出位置.我还为数组建议了一个'init'函数.但是,我没有放入"释放"功能.

注意这是C,而不是C++.如果您正在使用C++,那么您应该使用new或更好地使用C++ vector.

此外,在C++中使用静态时,请注意:C++静态初始化顺序


小智 8

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

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

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

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.
Run Code Online (Sandbox Code Playgroud)

支持(来源):

  • MSVC 自版本 19.12 (VS 2017 15.5)
  • 海湾合作委员会 7
  • 叮当 3.9
  • 国际商会 18.0

在这种情况下,这意味着您可以更换

static int *pieces;
Run Code Online (Sandbox Code Playgroud)

inline int *pieces;
Run Code Online (Sandbox Code Playgroud)