【C++】命名空间
🏖️作者:@malloc不出对象
⛺专栏:C++的学习之路
👦个人简介:一名双非本科院校大二在读的科班编程菜鸟,努力编程只为赶上各位大佬的步伐🙈🙈
目录
- 前言
- 一、命名空间产生的背景
- 二、命名空间的定义
- 三、命名空间的使用
- 四、从多个角度分析为什么不提倡使用using namespace
- 4.1 如何合理使用using namespace std
- 4.2 \<iostream> 与<iostream.h>的关系
- 五、如何合理使用命名空间来避免命名冲突
前言
本篇文章将给大家讲述的是命名空间,它是C++中为了解决命名冲突所引申出的一种解决方案,我们使用C++常用的using namespace std;std就是C++标准库的命名空间名称,也许有小伙伴兴许还不知道这句代码表示什么含义,下面就让我们进行命名空间的学习吧!!
一、命名空间产生的背景
我们首先来看一个例子:

C++是向下兼容C语言的语法的,在这段代码中使用rand发生了重定义,因为在C中rand是头文件stdlib.h中的一种库函数,而现在我们将rand作为普通变量名来使用这就造成了重命名,编译器不知道到底使用哪个rand,而在C语言中只能通过更换名称来解决这种命名冲突,可这其实是一个非常蛋疼的问题。
大型应用程序经常使用来自不同厂商的开发库,几乎不可避免会使用相同的名字,也就是说一个库中定义的名字可能与其他库中的名字相同而产生冲突。假如不同的程序员分别定义了类和函数,放在了不同的头文件中,在主函数的文件中需要使用这些类和函数时,就用#include指令将这些头文件包含进来,我们知道在预编译后#include头文件会将头文件的内容展开在源文件中,这样就在同一个程序文件中可能就会出现了多个名字相同的类或函数,这就造成了命名冲突,即在同一个作用域中有两个或者多个同名的实体,使得程序员不能组合各自独立的开发库到一个程序中。
对此ANSI C++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突。
命名空间是用来限定名字的解析和使用范围,它是C++开发大型程序的工具之一。命名空间的原理是将全局作用域划分为一个一个的命名空间,每个命名空间是一个独立的作用域,在不同命名空间内部定义的名字彼此之间互不影响,从而有效的避免了命名污染。
二、命名空间的定义
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
下面就是一个简单的命名空间:

命名空间可以在全局作用域或其他命名空间内部定义,但不能在函数、结构体或类内部定义,且要保证命名空间之间不会出现名字冲突。
在命名空间作用域内,可以包含:变量、对象以及它们的初始化、枚举常量、函数声明以及函数定义、类、结构体声明与实现、模板、其他命名空间。每个命名空间是一个作用域,定义在命名空间中的实体称为命名空间成员,命名空间中的每个名字必须是该命名空间中的唯一实体,但不同命名空间可以具有同名成员。
// 1. 正常的命名空间定义
namespace Curry1
{// 变量、函数、结构体....int a;void func1(){//...}struct Node{struct Node* next;int val;};//...
}// 2. 嵌套的命名空间定义
namespace Curry1
{// 变量、函数、结构体....int a;void func1(){//...}struct Node{struct Node* next;int val;};namespace Curry2{int b;void func2(){//...}}//...
}// 3.同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中
namespace Curry1
{// 变量、函数、结构体....int a;void func1(){//...}//...
}namespace Curry1
{int b;int Add(int a, int b){return a + b;}//...
}
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
三、命名空间的使用
命名空间有三种使用方式:
第一种使用方式:命名空间名称::xxx

这种命名空间的方式是三种之中最繁琐的一种方式,因为它需要我们一个个去指定命名空间域,但同时它却是最安全的一种方式,它避免了命名空间被污染。
这个地方还有一种使用域运算符引用全局命名空间的成员的方式,下面我们简单的看一个例子:

::xxx 表示引用全局命名空间成员,我们可以这样来简单的理解一下,域运算符左边为空就代表全局命名空间域。所以 ::xxx就可以表示直接引用xxx全局命名空间成员。
下面这里再补充一下嵌套命名空间的使用方式,我们一起来简单的看下:

第二种:using 命名空间名称::xxx

将std C++标准库中经常使用的少数几个成员使用using 命名空间名称::xxx部分展开,使用一部分暴露一部分,这样在一定程度上也减少了命名空间被污染,到后面我个人也是偏提倡这种使用命名空间的方式。
第三种:using namespace 命名空间名称

using namespace Curry1将Curry1命名空间域中的内容全局展开,所以我们的变量a以及Add函数可以直接进行使用,,这种方式最为方便直接令整个命名空间成员都有效,但同时这种全局展开的方式是最不安全的,下面我会带大家详细探究这个问题。
四、从多个角度分析为什么不提倡使用using namespace
1.首先我们这里特别强调尤其不要在头文件中使用using namespace。
我们知道#include头文件会在预处理阶段将头文件的内容展开到源文件中,如果将using namespace包含在头文件中那么随着会在源文件中全局展开,那么此时的命名空间就被污染了,换而言之就是使用using namespace全局展开之后命名空间域就消失了,我们在.cpp中写的代码很有可能会与using namespace命名空间域中的变量、函数、类等发生重名冲突。
在大工程中如果出现此类问题是很难去追查错误源头的,尤其像有多个文件嵌套包含了using namespace,你该如何去进行追查错误源头?这无疑为我们带来了巨大的维护成本。
上述关于尽量不要在头文件中使用using namespace,这就话本质就是在 “尽量不扩大using namespace xxx所影响到的域”,所以我们可以写在cpp文件中使其控制在一个编译单元内,也可以写在函数里控制在一个函数中,这样都一定程度上控制了using namespace所影响到的域的范围。
对于在源文件中使用using namespace,有一部分大佬则是持开放的态度认为源文件中可以随便在源文件中使用using namespace,因为.cpp文件不影响他人的使用;而对于这一点我的看法还是不能在任何情况下滥用using namespace,在源文件中也会有一定的风险,下面我们来看一个例子:

上图例子由于A和B的命名空间域都是全展开的,此时编译器就不确定变量b到底使用哪个命名空间的。
同样的角度,假设命名空间A中定义了一个函数Add_1,命名空间B中定义了一个函数Add_2,它们两者全局展开,,此时我们即可以使用函数Add_1又可以使用函数Add_2,但是以后假设A命名空间升级了也加入了一个函数Add_2,那么这时候我们原来的代码就有问题了,我们编译器到底使用的是命名空间A的Add_2还是命名空间B的Add_2呢?此时就发生了命名冲突,如果是一个大工程的话,假设命名空间A就是我们的C++标准命名空间,命名空间B是公司成员写的代码,此时C++标准命名空间升级了,那么此时这个公司之前写的代码就跑不过去了,这样就带来很大的损失…
2. 其次使用using namespace与命名空间设计的初衷背道而驰了。
本身namespace就是给你一个限定名字域的作用的,但是你using之后就相当于没有了命名空间域,因为using namespace将这个命名空间域全部展开暴露在文件中了嘛!!更通俗的来讲站在命名空间的角度使用using namespace跟没使用是一样的!!!
这里可能有读者还不明白,这里我举一个例子:当你用C++标准库STL的cout时,同时引用了命名空间域A中的cout,此时编译器不知道你要用的是std::cout还是A::cout,所以要想避免命名冲突你还是得显式的写std::cout与A::cout,这样看来using namespace是不是就没什么用了而且还带了一些麻烦。
Q:那么有读者可能会问那为啥要设计出using namespace这种使用命名空间的方式呢?
首先我认为设计者觉得在一些情况下使用using namespace是非常方便的,就如我们上个话题谈到的不涉及大量重名的、大型项目中的;其次也许设计者在设计时没考虑全展开重名呢,仅仅是觉得有些场景下使用起来方便所以设计出来的呢,,不管处于什么原因我认为存在即合理!!
总的来说,我认为不应该抹杀任何一种使用方式,我们只是站在不同的角度去辩证的看待这三种方式带来的问题。
4.1 如何合理使用using namespace std
通过上述我们对using namespace做的一系列分析,我们也知道要尽量使用using namespace全局展开,std是C++标准库的命名空间,如何展开std使用更合理呢?
1.在日常练习中,建议直接using namespace std即可,这样就很方便。
2.using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现,所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 +using std::cout展开常用的库对象/类型等方式。
4.2 <iostream> 与<iostream.h>的关系
在我们之前的C语言学习当中,我们见到的想必都是.h头文件这种形式,但是在C++引入命名空间之后,C++新的标准为了和C区别开来规定头文件不使用后缀.h,另外C++为了兼容C,在C++标准化过程中,原有C语言头文件标准化后头文件名前带个c,例如cstdio、cstring、cstdlib等…
Q:那么在C++新的标准中<iostream>与<iostream.h>一样吗?
答案是不一样,这俩者是两个不同的文件,当使用<iostream.h>时相当于在C中调用库函数,使用的是全局命名空间,也就是早期C++的实现;当使用<iostream>时,该文件没有定义全局命名空间必须加上using namespace std;这样才能使用C++标准库中的类、函数等…这也就是我们经常写.cpp时通常头文件和using namespace std;缺一不可的原因。
五、如何合理使用命名空间来避免命名冲突
一般情况下,对偶尔使用命名空间的成员应该使用命名空间的作用域解析运算符来直接给名称定位,这是最为安全的一种方式;而对一个大空间中经常要使用的少数几个命名空间成员提倡使用using 命名空间名称::声明,我个人也是偏提倡一点这种使用方式,对于少数几个命名空间成员来讲它污染的命名空间域范围较小,因为毕竟第一种方式确实对于一个繁琐使用的少数命名空间成员不是很友好;对于最后一种using namespace全展开命名空间域其实是最不提倡使用的,因为它会带来很多风险。但对于现阶段的我们来说,在平时的一些练习、竞赛以及项目小没有很多重名的时候,我们使用using namespace是可行的,因为它确实很方便并不需要我们过多去考虑命名冲突的风险,但使用using namespace终究还是有未知的风险的,我们不要在平时太依赖using namespace这种命名方式了。糖果虽甜,但吃多了就会有蛀牙🙈🙈
对于以后自己参加工作编写项目时,我个人的看法是将自己写的函数、类放在自己的命名空间,使用的时候不管是哪个命名空间里的,都要指明出处,都不要全部展开!!!因为你不知道什么时候风险会降临到你身边orz~
本篇文章的讲解就到这里了,如果有任何错处或者疑问欢迎大家评论区交流哦~~ 🙈 🙈
相关文章:
【C++】命名空间
🏖️作者:malloc不出对象 ⛺专栏:C的学习之路 👦个人简介:一名双非本科院校大二在读的科班编程菜鸟,努力编程只为赶上各位大佬的步伐🙈🙈 目录前言一、命名空间产生的背景二、命名空…...
【AutoSAR】【MCAL】Dio
一、结构 二、功能介绍 DIO(数字输入输出)驱动模块主要是对端口(Port),通道(Channel)和通道组(ChannelGroup)进行读写操作。 通道(Channel)&…...
瑞吉外卖——day2
目录 一、新增员工 二、查询分页数据 三、启用、禁用员工账户、编辑员工信息 一、新增员工 点击左上角新增员工 页面如下: 我们随便填数据 ,点击保存,请求的地址如下 返回前端可以看到请求方式为Post 在employeeController中编写对应的代…...
了解java
#常见编程语言介绍 C语言 C语言 java语言 javaScript语言 PHP语言 python语言Object-C和Swift语言 C# (c sharp)语言 Kotlin语言 Go语言 Basic语言 #JAVA的发展 起源于1991年SUN公司GREEN项目,1996年JDK1.0正式发布 后被Oracle公司收购&…...
【编程实践】代码之中有创意:“我一直认为工程师世界上最具创造性的工作之一”
代码之中有创意 “我一直认为工程师世界上最具创造性的工作之一”。 文章目录 代码之中有创意一、代码可以赋予创造力1.1 代码的创造力1.2 如何发挥代码的创造力二、有创意的代码可以提高工作效率2.1 代码创意可以提高工作效率2.2 如何利用代码创意来提高工作效率三、代码创意可…...
【MySQL】表连接
一、为什么要学习 因为不合理的使用连接会导致慢查询 二、什么是连接 参与连接的表叫做 连接表, 连接就是把 各个连接表 进行的组合 (笛卡儿积)加入结果集并返回 三、连接查询 如何只是对表进行大量的连接,笛卡儿积作用得到的…...
2023湖南省“楚怡杯”职业技能大赛“网络安全” 项目比赛任务书
2023湖南省“楚怡杯”职业技能大赛“网络安全” 项目比赛任务书2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书A模块基础设施设置/安全加固(200分)A-1:登录安全加固(Windows, Linux)A-2:Ngi…...
Android应用启动优化笔记整理
应用启动相关流程与优化 应用启动主要涉及SystemServer进程 和 app进程。 SystemServer进程负责app进程创建和管理、窗口的创建和管理(StartingWindow 和 AppWindow)、应用的启动流程调度等。 App进程被创建后,进行一系列进程初始化、组件初…...
图像bytes字节串二进制转十六进制及bytes转为图像
目录前言正文二进制与十六进制的bytes互转读取bytes为图像法1:直接写入f.read的结果法2: 转换为PIL或Numpy前言 参考: 8. python基础之基础数据类型–bytes - CSDN python 16进制与图片互转 - CSDN 正文 二进制与十六进制的bytes互转 bytes保存的是原始的字节(二…...
信息安全与数学基础-笔记-②同余
知识目录同余完全剩余系剩余类完全剩余系❀简化剩余系❀欧拉函数逆元!欧拉定理 !同余 a,b 两个数字,都模m,当两个数字模m后余的数一样即为同余。 例子: a bq r (mod m),这里的a 和 r 就是同余 ÿ…...
网络安全法
目录正文第一章第二章第三章第四章第五章第六章 法律责任第七章 附则正文 学习网络安全应该知道网络安全法 第一章 总则 第一条: 为了保障网络安全,维护网络空间主权和国家安全、社会公共利益,保护公民、法人和其他组织的合法权益,促进经济…...
django框架开发部署项目
前言:相信看到这篇文章的小伙伴都或多或少有一些编程基础,懂得一些linux的基本命令了吧,本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python:一种编程语言&…...
Unity记录1.3-入门-第一阶段总结
文章首发及后续更新:https://mwhls.top/4447.html,无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评,非常感谢! 汇总:Unity 记录 摘要:第一阶段的总…...
Linux入门篇-文件管理
简介 简单的文件管理。 ⽂件内容的查看 ⽂本⽂件内容的查看 cat ⽂本⽂件的path1 ⽂本⽂件的path2 head ⽂本⽂件的path ,显示⽂件的前10⾏内容 head -n 5 ⽂本⽂件的path , 显示⽂件的前5⾏内容 head -5 等于head -n 5tail ⽂本⽂件的path, 显示⽂件的后10⾏内容…...
如何从错误中成长?
在上一篇文章“技术人的犯错成本”里,我和你聊了技术人可能会犯的各式各样的错误,也举了很多例子,说明了技术人犯错的成本。在竞争激烈的互联网时代,试错当然是好事,但了解错误成本,避免不应该犯的错误&…...
谈谈一个程序员的职场心得(真有用)
谈谈一个程序员的职场心得 我会分为三个部分:软件开发,职场协作和认知成长,每个部分精简成 7 条心得。 软件开发 若无必要,勿增实体。 这是奥卡姆剃刀的定义,所谓剃刀就是法则,是奥卡姆这个英国学者提出来…...
Pytest:一个卓有成效的测试工具
大家都知道,目前最流行的Python单元测试框架有三种,分别是unittest, nose和pytest。其中unittest是Python自带的测试框架,但问题是比较老了,赶不上时代发展了(哈哈哈);nose2定位是带插件的unitt…...
Compose 动画 (三) : AnimatedVisibility 从入门到深入
1. AnimatedVisibility 是什么 AnimatedVisibility可以实现Compose组件的显示和隐藏,并且可以指定显示/隐藏时候的动画效果。(EnterTransition/ExitTransition) 和 animateXxxAsState、animateContentSize、Crossfade、AnimatedContent 这几个API一起,都…...
网络基础(二)
目录 应用层 再谈 "协议" 协议是一种 "约定". socket api的接口, 在读写数据时, 都是按 "字符串" 的方式来发送接收的. 如果我们要传输一些"结构化的数据" 怎么办呢? 为什么要转换呢? 如果我们将struct message里面…...
Java线程知识点总结
文章目录Java 线程基础线程简介什么是进程什么是线程进程和线程的区别创建线程ThreadRunnableCallable、Future、FutureTaskCallableFutureFutureTaskCallable Future FutureTask 示例线程基本用法线程休眠线程礼让终止线程守护线程线程通信wait/notify/notifyAlljoin管道线程…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践
在电商行业蓬勃发展的当下,多平台运营已成为众多商家的必然选择。然而,不同电商平台在商品数据接口方面存在差异,导致商家在跨平台运营时面临诸多挑战,如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...
数据库优化实战指南:提升性能的黄金法则
在现代软件系统中,数据库性能直接影响应用的响应速度和用户体验。面对数据量激增、访问压力增大,数据库性能瓶颈经常成为项目痛点。如何科学有效地优化数据库,提升查询效率和系统稳定性,是每位开发与运维人员必备的技能。 本文结…...
华硕电脑,全新的超频方式,无需进入BIOS
想要追求更佳性能释放 或探索更多可玩性的小伙伴, 可能会需要为你的电脑超频。 但我们常用的不论是BIOS里的超频, 还是Armoury Crate奥创智控中心超频, 每次调节都要重启,有点麻烦。 TurboV Core 全新的超频方案来了 4不规…...

