☰
共享变量一 关于extern与const
2026/10/30 2:41:23 网站建设 项目流程

在 C++ 中,extern关键字主要用于声明变量或函数(告诉编译器“这个变量/函数在别的地方定义了”),或者用于改变const变量的默认链接属性。

普通变量和const变量在使用extern时,最核心的区别在于:默认的链接属性(Linkage)不同。

  • 普通全局变量:默认具有外部链接(External Linkage),可以被其他文件访问。访问的是同一个对象,地址相同

  • const全局变量:默认具有内部链接(Internal Linkage),仅在当前文件可见(相当于默认加了static)。这是 C++ 为了防止头文件中定义const变量导致多重定义冲突而设计的。当然也可以被多个文件同时访问,但访问的是否是同一个对象,地址是否相同,看你怎么定义和声明

这里说防止头文件中定义const变量导致多重定义冲突是什么意思?可以看这篇文章:

const 全局变量默认具有内部链接为什么可以防止头文件导致出现多重定义问题

那难道就不怕普通全局变量在头文件中导致多重定义冲突吗,不怕,头文件里面编译器就不给你定义普通变量,只允许你在头文件里面声明普通变量。

下面通过具体的代码场景来演示这种区别:

场景:在多个源文件中共享全局变量,注意是源文件,没有头文件

假设我们有两个文件:main.cpp和other.cpp。

1. 普通变量的extern使用

对于普通变量,在定义时不需要加extern。在别的文件中使用时,用extern声明一下即可。

other.cpp(定义)

int global_num = 100;

main.cpp(使用)

#include <iostream> // 声明:告诉编译器 global_num 在别的文件里定义过 extern int global_num; int main() { std::cout << "普通变量: " << global_num << std::endl; // 输出 100 return 0; }
2.const变量的extern使用

声明 处加extern是必须的,且定义处也必须加extern

如果直接在other.cpp写const int const_num = 200;

int global_num = 100; const int const_num = 200;

然后在main.cpp写extern const int const_num;

#include <iostream> // 声明:告诉编译器 global_num 在别的文件里定义过 extern int global_num; //声明:告诉编译器 const_num在别的文件里定义过 extern const int const_num; int main() { std::cout << "普通变量: " << global_num << std::endl; // 输出 100 std::cout << "const变量: " << const_num << std::endl; return 0; }

链接会报错(undefined reference),注意,vscode编译语法校验不会直接报红,是可以通过的,使用ctrl+alt+b或者使用g++指令去编译出exe才会报错

其中最重要的报错信息:

undefined reference to `const_num'

因为other.cpp里的const_num默认是内部链接,main.cpp找不到它。

要共享const变量,定义时必须显式加上extern,强制将其改为外部链接。

other.cpp(定义)

int global_num = 100; // 必须加 extern,强制将其变为外部链接,否则 main.cpp 找不到 extern const int const_num = 200;

main.cpp(使用)

#include <iostream> // 声明:告诉编译器 global_num 在别的文件里定义过 extern int global_num; //声明:告诉编译器 const_num在别的文件里定义过 extern const int const_num; int main() { std::cout << "普通变量: " << global_num << std::endl; // 输出 100 std::cout << "const变量: " << const_num << std::endl; return 0; }

对于const变量,如果想在多个源文件共享。声明 处加extern是必须的,且定义处也必须加extern,注意,是源文件间共享,也就是.cpp文件之间共享



如果是头文件里面直接定义const变量,可加extern也可不加

一般,我们会将一些供多个文件使用的变量放在一个头文件,而这些变量通常是const变量

config.h

const int aaaa = 10;

注意,在头文件中,在头文件中,在头文件中,重要的事情说三遍

非const变量只能在头文件声明,不能定义

下面的写法是错误的:

int test_int = 10;

只能声明,如这么写:extern int test_int;

对的,你还得加上extern,因为你如果只在头文件写了int test_int;编译器还是认为你定义了一个初始值为0的int

但是,一般我们不会在头文件声明一个普通变量,只是给大家讲解一下注意事项

TestConfig1.cpp

#include <iostream> #include "config.h" void print_from_file1() { std::cout << "[file1] aaaa 的值: " << aaaa << ", aaaa 的地址: " << &aaaa << std::endl; }

TestConfig2.cpp

#include <iostream> #include "config.h" void print_from_file2() { std::cout << "[file2] aaaa 的值: " << aaaa << ", aaaa 的地址: " << &aaaa << std::endl; }

main.cpp

// 声明其他文件里的函数 void print_from_file1(); void print_from_file2(); int main() { print_from_file1(); print_from_file2(); return 0; }

可以看到,在cpp中,如果const变量写在头文件里面,const变量不需要写extern 就可以把这个变量给多个文件使用,只要需要使用这个变量的源文件引用头文件就可以了。

但是

看一下运行结果

[file1] aaaa 的值: 10, aaaa 的地址: 0x7ff712a49320 [file2] aaaa 的值: 10, aaaa 的地址: 0x7ff712a49350

可以看到不同文件的aaa的值的内存是不一样的,它们不是同一个变量。这也是文章开头说的,这是 C++ 为了防止头文件中定义const变量导致多重定义冲突而设计的。

如果需要aaa都是同一个内存以节约一点内存,可以在声明处都加上extern

config.h

// 直接在头文件中定义 const 变量 extern const int aaaa = 100;

TestConfig1.cpp

#include <iostream> #include "config.h" void print_from_file1() { std::cout << "[file1] aaaa 的值: " << aaaa << ", aaaa 的地址: " << &aaaa << std::endl; }

TestConfig2.cpp

#include <iostream> #include "config.h" void print_from_file2() { std::cout << "[file2] aaaa 的值: " << aaaa << ", aaaa 的地址: " << &aaaa << std::endl; }

main.cpp

#include "config.h" #include <windows.h> // 必须包含这个头文件,使vscode支持中文输出 // 声明其他文件里的函数 void print_from_file1(); void print_from_file2(); //定义这里不必加extern const int aaaa = 30; int main() { // 设置控制台输出编码为 UTF-8 SetConsoleOutputCP(65001); print_from_file1(); print_from_file2(); return 0; }

将aaaa的定义放在了main.cpp里面了

运行结果

[file1] aaaa 的值: 30, aaaa 的地址: 0x7ff748439000 [file2] aaaa 的值: 30, aaaa 的地址: 0x7ff748439000

可以看到,aaaa的地址是同一个,它们是同一个变量

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询