如何正确初始化全局变量?

6

我是一位有用的助手,可以为您进行文本翻译。

我正在撰写一个小型学生项目,遇到了一些问题。我有几个全局变量需要在几个源文件中使用,但是出现了错误信息 undefined reference to variable_name。例如,我们创建三个源文件:

tst1.h:

extern int global_a;
void Init();

tst1.cpp:

#include "tst1.h"
void Init(){
  global_a = 1;
}

tst2.cpp:

#include "tst1.h"
int main(){
  Init();
}

当我编译和链接时,会得到以下结果:
$ g++ -c tst1.cpp 
$ g++ -c tst2.cpp 
$ g++ tst2.o tst1.o
tst1.o: In function `Init()':
tst1.cpp:(.text+0x6): undefined reference to `global_a'
collect2: error: ld returned 1 exit status

如果我删除extern语句,那么我会遇到另一个问题,让我来展示一下:
$ g++ -c tst1.cpp 
$ g++ -c tst2.cpp 
$ g++ tst2.o tst1.o
tst1.o:(.bss+0x0): multiple definition of `global_a'
tst2.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

我需要一些全局变量,比如我的小项目涉及汇编代码,并且有像 string rax = "%rax %eax %ax %ah %al"; 这样的变量,应该通过不同的源文件来引用。

那么,如何正确初始化全局变量呢?


2
最好的解决方案是不使用全局变量。如何避免它们的提示是:依赖注入。 - Tim Seguine
@Tim,我知道全局变量不是好的编程风格,但在某些情况下它是正确的方式。例如,如果我的项目使用汇编语言,则许多文件都需要知道CPU寄存器的名称,并且变量string rax =“%rax%eax%ax%ah%al”应该通过不同的源文件进行引用。 - Hi-Angel
一般情况下,应该优先使用静态类成员。 - leemes
3个回答

6

您只声明了变量,但没有定义它。此记录

extern int global_a;

这是一个声明而不是定义。要定义它,您可以在任何模块中编写:

int global_a;

或者更好的方法是这样定义函数 init:
int Init { /* some code */; return 1; }

在主模块中,在 main 函数之前编写以下内容。
int global_a = Init();

正如我在下面评论的那样,编译器显示 tst1.cpp:2:5: error: redefinition of ‘int global_a - Hi-Angel
很抱歉,我不明白你的评论。我展示了相关的代码。你不能简单地复制粘贴吗? - Vlad from Moscow
我只是在tst1.cpp中写了一个全局作用域的int global_a;。编译器报错了。 - Hi-Angel
你应该将声明放在头文件中。我已经写好了你需要的内容。有什么问题吗? - Vlad from Moscow
哦,抱歉,我是个傻瓜 :) 我通过一些实验删除了 extern 语句。没错。 - Hi-Angel
声明应该是所有模块都能看到变量并知道它是同一个变量。祝好运! - Vlad from Moscow

2

tst1.cpp应该改为:

#include "tst1.h"

int global_a = 1;

void Init(){  
}

你可以将初始化器行写成以下形式:
int global_a(1);

或者在C++11中:

int global_a{1};

全局变量应该只在一个源文件中被 定义(即不使用 extern 前缀),而不是在头文件中。


不,这就是我得到的: tst1.cpp:2:5: 错误:重定义‘int global_a’ int global_a = 33; ^ 在文件 tst1.cpp 中包含: tst1.h:1:5: 错误:‘int global_a’ 在此前已经声明过 int global_a; ^ - Hi-Angel
抱歉,格式可能有些混乱,简要来说就是“tst1.cpp:2:5: error: redefinition of ‘int global_a’”,意思是“int global_a 的重新定义”。 - Hi-Angel
我假设你的tst1.h文件里有extern int global_a;,正如你在问题中所写的那样,而不仅仅是int global_a; - Mike DeSimone
没错,但同时有两个正确答案。我选择了其中一个,这是作者给出的答案。 很抱歉,无法选择两个正确答案,尽管我想过并尝试过。 - Hi-Angel
没问题。只是有时候别人发布的代码和他们想要构建的代码不一样,这很让人烦恼。 - Mike DeSimone

0

你需要添加

#ifndef TST1_H
#define TST1_H
.....
#endif 

to tst1.h. it included twice in tst2.cpp


1
不,它不是被包含两次,而是在不同的翻译单元中编译两次。使用预编译指令并不能解决这个问题。 - leemes

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