多文件编译下static变量地址与this不一致问题咨询
关于static全局变量的两个疑问
我在测试中编写了以下代码:
Foo.h代码
struct Foo { Foo(); void dummy(){} }; static Foo foo;
Foo.cpp代码
#include "Foo.h" #include <iostream> Foo::Foo() { std::cout<<&foo<<std::endl; std::cout<<this<<std::endl; };
main.cpp代码
#include "Foo.h" // 注:原代码写为#include "a.h",应为笔误 int main(){ foo.dummy(); }
运行后输出:
0x7f333ff1077e 0x7f333ff1077e 0x7f333ff1077e 0x7f333ff1077c
疑问:
- 为何会出现两个不同的地址?实际是创建了两个static变量吗?
- 为何构造函数中
&foo和this的地址会不一致?
另外,如果把所有代码合并到单个头文件中,输出符合预期:
0x7f385b59973f 0x7f385b59973f
问题解答
确实创建了两个独立的static变量
C++里,static修饰的全局变量作用域仅限于当前编译单元。当头文件被多个编译单元(Foo.cpp和main.cpp)包含时,每个编译单元都会独立生成一份static Foo foo的实例。所以这里实际存在两个完全独立的foo对象,分别归属Foo.cpp和main.cpp两个编译单元。&foo与this地址不一致的原因
构造函数Foo::Foo()是全局可见的函数,但函数内的foo会解析为Foo.cpp编译单元里的static变量(因为构造函数定义在Foo.cpp中)。
- 当Foo.cpp中的
foo构造时,&foo和this都指向这个实例,所以前两行地址相同; - 当main.cpp中的
foo构造时,调用的是同一个构造函数,此时&foo仍然指向Foo.cpp里的foo,但this指向的是正在构造的main.cpp里的foo,因此出现了地址不一致的情况(第三行是Foo.cpp的foo地址,第四行是main.cpp的foo地址)。
合并到头文件的情况
当所有代码放在单个头文件时,整个程序只会生成一个编译单元,因此只会创建一个static Foo foo实例。构造函数执行时,&foo和this指向同一个对象,所以输出的地址完全相同。
内容的提问来源于stack exchange,提问作者cppBeginner
相关产品推荐
相关产品推荐

