`using`与`using namespace`声明的区别及相关编译疑问解答
技术问题1:为何在示例(1)的main函数中无法声明局部变量
i,但示例(2)中可以? 示例(1)代码
namespace X { int i = 5; } int main() { using X::i; i = 10; std::cout << i << '\n'; // 10 std::cout << X::i << '\n'; // 10 // int i = 22; // error: 'int i' conflicts with a previous declaration }
示例(2)代码
namespace X { int i = 5; } int main() { using namespace X; int i = 10; std::cout << i << '\n'; // 10 std::cout << X::i << '\n'; // 5 }
解答
- 示例(1)里的
using X::i;是名字声明式引入:它直接把命名空间X中的i带入main函数的局部作用域,相当于该作用域内已经有了一个名为i的实体声明。此时再在main里声明局部变量i,违反了「同一作用域内不能存在同名实体」的规则,所以编译报错。 - 示例(2)里的
using namespace X;是命名空间指令引入:它只是把X内的名字加入当前作用域的查找候选列表,并没有在当前作用域创建新的名字声明。当声明局部变量i时,局部作用域的实体优先级高于命名空间引入的名字,局部i会直接隐藏X::i,因此不会产生冲突,编译通过。
技术问题2:为何在示例(3)中直接对
i赋值会出现“reference to 'i' is ambiguous”的编译错误? 示例(3)代码
int i = 11; namespace X { int i = 22; } using namespace X; int main() { std::cout << ::i << '\n'; // 11 std::cout << X::i << '\n'; // 22 // i = 33; // error : reference to 'i' is ambiguous }
解答
示例(3)中,全局作用域本身存在一个i,同时using namespace X;将命名空间X中的i引入到全局作用域的名字查找候选中。在main函数里直接使用i时,编译器需要解析这个名字:它既可以匹配全局作用域的::i,也可以匹配X::i,两者的查找优先级完全相同,编译器无法确定应该使用哪一个,因此抛出「引用歧义」的编译错误。
内容的提问来源于stack exchange,提问作者rand_program
相关产品推荐
相关产品推荐

