48

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

static int *pieces;

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

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

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

4

4 回答 4

97

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

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

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


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

您可以使用new int[128]()而不是更冗长的malloc语法,这也会执行初始化吗?或者你可以走简单的路(这就是它的用途)并使用std::vector

于 2013-01-16T01:13:26.563 回答
29

关键是这样的:

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++ 静态初始化顺序

于 2013-01-16T01:16:17.470 回答
9

在 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.

支持(来源):

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

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

static int *pieces;

inline int *pieces;
于 2018-10-19T07:40:17.847 回答
2

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

于 2016-06-18T20:20:28.103 回答