C++中同一static变量何时会被编译器生成两个独立实例?
以下几种情况,编译器会为看似“同一个”static变量生成完全独立的实例:
1. 同名static全局变量定义在多个编译单元
static全局变量具备内部链接特性,仅在其所在的编译单元(.cpp文件)内可见。如果在不同的.cpp文件中分别定义了同名的static全局变量,编译器会为每个编译单元单独分配内存,生成完全独立的实例,彼此互不干扰。
示例代码:
// file1.cpp static int global_counter = 0; void add_to_file1() { global_counter++; } int get_file1_counter() { return global_counter; } // file2.cpp static int global_counter = 0; void add_to_file2() { global_counter++; } int get_file2_counter() { return global_counter; }
调用add_to_file1()只会修改file1中的实例,调用add_to_file2()修改的是file2中的实例,两者数值完全独立。
2. 模板中的static成员/局部变量被不同类型实例化
当模板类或模板函数包含static成员,或者模板函数内有static局部变量时,每种不同的模板实例化类型都会触发编译器生成该static变量的独立实例。
示例代码:
// 模板类的static成员 template<typename T> class TypeCounter { public: static int instance_count; TypeCounter() { instance_count++; } }; template<typename T> int TypeCounter<T>::instance_count = 0; // 模板函数的static局部变量 template<typename T> void track_call() { static int call_times = 0; call_times++; }
这里TypeCounter<int>::instance_count和TypeCounter<std::string>::instance_count是两个独立变量;调用track_call<int>()和track_call<double>()时,操作的也是各自独立的call_times实例。
3. 静态库中的static变量被多个可执行文件链接
当包含static变量的代码被编译为静态库时,每个链接该静态库的可执行文件都会将static变量的实例复制到自身的二进制文件中。这意味着不同的可执行文件运行时,使用的是完全独立的static变量实例,彼此无关联。
4. 动态库被多次加载时的static变量
如果将包含static变量的代码编译为动态库,并且通过dlopen(Linux)或LoadLibrary(Windows)等方式多次加载该动态库(比如在同一个进程中加载多次),每次加载都会生成一份独立的static变量实例。此外,不同进程加载同一个动态库时,每个进程也会拥有该动态库中static变量的独立副本。
内容的提问来源于stack exchange,提问作者MBagher

