全局变量存在时,如何用作用域解析符访问未命名命名空间?
问题:全局变量存在时,如何访问未命名命名空间中的变量?
原始代码
#include <iostream> using namespace std; // 命名空间first中的变量 namespace first { int val = 500; } // 未命名命名空间中的变量 namespace { int val = 400; } // 全局变量(当前为注释状态) //int val = 100; int main() { // 局部变量 int val = 200; // 通过作用域运算符访问不同作用域的变量 cout << first::val << '\n'; cout << ::val << '\n'; cout << val << '\n'; return 0; }
场景说明
- 当注释掉全局变量
int val = 100;时,::val会解析为未命名命名空间中的val = 400,程序输出为:500 400 200 - 取消注释启用全局变量后,
::val会指向全局变量val = 100,程序输出变为:500 100 200
此时需要解决的问题是:如何在全局变量存在的情况下,访问未命名命名空间中的val?
解决方案
未命名命名空间的名字是编译器自动生成的唯一标识符,无法直接通过作用域运算符::写出它的名字来访问成员,因此可以通过以下两种实用方法间接访问:
方法1:提前定义引用捕获未命名命名空间的变量
在全局变量声明之前,定义一个引用指向未命名命名空间的val——此时全局变量还未声明,编译器会将val解析为未命名命名空间的成员:
#include <iostream> using namespace std; namespace first { int val = 500; } namespace { int val = 400; } // 定义引用捕获未命名命名空间的val(此时全局val尚未声明) int& unnamed_val = val; // 启用全局变量 int val = 100; int main() { int val = 200; cout << first::val << '\n'; // 输出500 cout << ::val << '\n'; // 输出100(全局变量) cout << unnamed_val << '\n'; // 输出400(未命名命名空间的val) cout << val << '\n'; // 输出200(局部变量) return 0; }
方法2:在未命名命名空间内添加访问函数
在未命名命名空间中定义一个函数,返回内部val的引用,通过调用该函数即可获取未命名命名空间的变量:
#include <iostream> using namespace std; namespace first { int val = 500; } namespace { int val = 400; // 定义函数返回未命名命名空间的val引用 int& get_unnamed_val() { return val; } } // 启用全局变量 int val = 100; int main() { int val = 200; cout << first::val << '\n'; // 输出500 cout << ::val << '\n'; // 输出100(全局变量) cout << get_unnamed_val() << '\n'; // 输出400(未命名命名空间的val) cout << val << '\n'; // 输出200(局部变量) return 0; }
原理说明
未命名命名空间的成员仅在当前翻译单元内可见,当全局作用域存在同名变量时,直接通过val或::val会优先匹配全局变量。由于无法直接写出未命名命名空间的名字,只能通过提前绑定引用或提供内部访问接口的方式,绕过名字冲突问题,持续访问到未命名命名空间的成员。
内容的提问来源于stack exchange,提问作者Johnz
相关产品推荐
相关产品推荐

