C++ 面试高频:namespace 的 6 个知识点,从 using 到匿名命名空间

在 C++ 中,命名空间(namespace)用来把类、函数、变量等标识符封装起来,避免命名冲突和名字污染------这是它最基础的作用。`using 声明` 和`using 指令` 到底差在哪、为什么头文件里不能用`using namespace std` 、从定义到嵌套、内联命名空间、别名一路讲下来,最后都落到这几个必考问题上。

命名空间里面是声明定义区域,不是执行代码的地方。

所以命名空间里面放各种声明和定义,不能放执行代码的

所以不同命名空间也算不同作用域

一、命名空间的特性

1.命名空间只能放全局函数外面,所以命名空间的成员都是全局变量

2.不同命名空间算不同作用域,所以即使都处于全局但也有不同作用域

3.命名空间里面可以放数据类型,函数声明和定义,结构体等等甚至放另一个命名空间

命名空间是什么?

定义一个命名空间格式是

namespace 命名空间名字

{

//声明定义变量 //命名空间里面的东西都算成员,只不过结构体成员没值,命名空间结构体可以有值

//函数声明和定义

//定义结构体/共用体/枚举 数据类型

//声明类 定义对象

//其他命名空间 //命名空间允许嵌套另一个命名空间

} //没有分号,结构体有分号

那么平时说的标准命名空间是什么?

是 using namespace std;

using是使用意思,namespace是命名空间意思,std是空间名

这里就不用再声明里面的东西了,因为这是C++标准库的命名空间

其余的命名空间要声明里面的东西,而标注命名空间不用

std是C++标准库的命名空间的空间名,意思是C++标准库里面的东西都放在std这个命名空间里面

cout、cin、string全部都装在std这个盒子里。

所以只要用了cout和cin就要写使用标准命名空间

当然自己定义其他空间名也行,但是标准库里面的东西只能放在std这个空间名里面C++写死了

using namespace std;意思是:打开 std 这个盒子,盒子里面东西直接拿出来用,不用写 std::

如果不写这个语句,那么后面代码的变量名要加空间名加域运算符::

空间名加域运算符::就是直接拿取空间名的成员

如

std::cout

域运算符有点像结构体,但是结构体只能放数据类型,而命名空间可以放很多东西

二、命名空间里面可以放什么东西?

命名空间里面是声明定义区域,不是执行代码的地方。

命名空间里面可以放:全局变量、函数、结构体、类、枚举、类型别名、嵌套命名空间。

不能放:预处理指令、局部变量。

命名空间主要放全局变量,函数声明和定义,类,结构体,还可以嵌套其他命名空间

命名空间不能放局部变量和可执行语句

匿名命名空间是什么

匿名结构体只无法间接定义结构体数据类型,匿名空间只是一个没有名字的空间,实际算有名字

匿名空间的语法格式

namespace

{

int val=100;

} //这就是一个匿名命名空间

匿名空间相当于命名空间没有空间名,没有空间名就用不了域运算符

所以他的成员的用法就不用写空间名加域运算符

如

#include

using namespace std;

namespace

{

int val=100;

}

int main()

{

cout

return 0;

}

三、匿名命名空间(无名命名空间)作用

匿名命名空间:namespace { ... },没有名字的命名空间

1.作用域限制:成员仅在当前源文件 (.cpp) 内可见,其他文件无法访问。

效果等价于static修饰全局变量 / 函数,实现文件内部私有。

2.本文件内部可以直接使用里面的成员,不需要写::作用域解析运算符。

3.避免全局名字冲突:把本文件内部要用的变量、函数放到匿名命名空间,不会和别的文件的全局名字发生冲突

匿名命名空间和全局变量的歧义性

命名空间也并非万能的,当匿名结构体和全局变量碰在一起会发生歧义,语法不通过

如

cpp 复制代码
//====单独全局变量的时候语法格式========
#include<iostream>
using namespace std;
int val=100;
int main()
{                                  //如果局部没有同名变量,`main`里直接用就是全局的`val`。
    cout<<"val的值是"<<val<<endl;   //结果为100
    return 0;
}
//====单独匿名结构体的时候语法格式======
#include<iostream>
using namespace std;
namespace 
{
    int val=300;
}
int main()
{
    cout<<"val的值是"<<val<<endl;   //结果为300
    return 0;
}
会发现cout打印全局变量和打印匿名结构体成员的时候语法格式一样
当他们一起碰在一起发生歧义性语法不通过
//===全局变量和匿名结构体一起打印同一个成员==============
#include<iostream>
using namespace std;
namespace 
{
    int val=300;
}
int val=100;
int main()
{
    cout<<"val的值是"<<val<<endl;   //此时语法不通过无法编译
    cout<<"val的值是"<<val<<endl;   
    return 0;
}
但是如果全局变量和匿名结构体和局部变量在一起
//===全局变量和匿名结构体和局部变量在一起打印同一个成员=====
#include<iostream>
using namespace std;
namespace 
{
    int val=300;
}
int val=100;
int main()
{
    int val;
    cout<<"val的值是"<<val<<endl;   
    cout<<"val的值是"<<val<<endl;   
    cout<<"val的值是"<<val<<endl;
    return 0;
}
打印结果:
val的值是200
val的值是200
val的值是200
因为除了运算符有优先级,变量之间也有优先级,变量之间的优先级针对是不同作用域,同一个变量名在代码块里面
变量的优先级看代码块就近原则,看代码块离哪个变量近,哪个变量在代码块里面
局部变量在代码块里面,第一个val,局部变量优先级最高,打印200,但此时会触发一个机制,加做名字遮蔽机制
300、100 这两个变量内存里的值仍然保留不变,只是名字val被局部变量 "遮蔽(shadow)",访问不到它们,不是把它们的值改成 200。
就记住发生名字遮蔽后,代码块里面所有的同一个变量名都变成优先级最高的那个变量名,自然就打印200
但是原本的其他优先级低的变量本身值还是不会被改的,只是此时优先级低的变量名在代码块看似失效了

四、变量名优先级和名字遮蔽机制

因为除了运算符有优先级,变量之间也有优先级,变量之间的优先级针对是在代码块里面同一个变量名在不同作用域

变量的优先级看代码块就近原则,看代码块离哪个变量近,哪个变量在代码块里面,哪个优先级就高

局部变量在代码块里面,第一个val,局部变量优先级最高,打印200,但此时会触发一个机制,加做名字遮蔽机制

300、100 这两个变量内存里的值仍然保留不变,只是名字val被局部变量遮蔽,访问不到它们,不是把它们的值改成 200。

就记住发生名字遮蔽后,代码块里面所有的同一个变量名都变成优先级最高的那个变量名,自然就打印200

但是原本的其他优先级低的变量本身值还是不会被改的,只是此时优先级低的变量名在代码块看似失效了

变量名的优先级对比

局部变量大于全局变量等于匿名命名空间成员,但全局变量和匿名命名空间在一起会产生歧义性

虽然局部变量优先级大于全局,局部会发生名字遮蔽机制,在C语言语法里面无法获得全局值但是在C++可以

C++在代码块里面局部和全局重名的情况下打印全局变量

cpp 复制代码
#include<iostream>
using namespace std;
int val=100;
int main()
{
    int val=200;
    cout<<"val的值是"<<val<<endl;     局部变量就是正常这样
    cout<<"val的值是"<<::val<<endl;   当不是命名空间的变量名前面加域域运算符,就默认这个变量是全局变量
    
    return 0;
}

C++中当不是命名空间的变量名前面加域运算符,就默认这个变量是全局变量

相关推荐
破芽1 小时前
learn-claude-code-s05-s11-学习笔记
笔记·学习
每天题库1 小时前
汽车维修工等级考试题库 理论实操核心考点一次梳理清
学习·安全·考试·题库·考证
神也畏惧菠萝2 小时前
想要学习Agent应用开发?:2026 AI Agent开发全栈通关路线
学习·langgraph·mcp协议·agent开发·rag架构·prompt高级工程
Navigator_Z2 小时前
LeetCode //C - 1300. Sum of Mutated Array Closest to Target
c语言·算法·leetcode
SZYSK2 小时前
鸿蒙人脸识别算法放在终端里:和外挂授权 SDK 差在排障路径
物联网·算法·华为·harmonyos
Zevalin爱灰灰2 小时前
Linux入门第一部分(Ubuntu入门篇) 第二章 浅尝Ubuntu(二)
linux·嵌入式·1024程序员节
程序猿乐锅2 小时前
【从0-1学习Python | 第七篇】Python 面向对象基础
开发语言·笔记·后端·python·学习·1024程序员节
Alsn863 小时前
JAVA通过 http api与ollama本地大模进行流式多轮对话
学习
凯瑟琳.奥古斯特3 小时前
力扣1016高效解法:剪枝优化技巧
开发语言·c++·算法·leetcode·职场和发展