详解:为什么尽量不要使用 using namespace std?

简介: C++辅导专栏

A:


需要保证的是尽量不要在头文件里 using 任何东西尤其是 namespace,要不然 include 进来的时候很容易莫名其妙产生命名冲突。


有条件的话,所有引入的符号都定义在自己的 namespace 里。任何情况下都不要 using namespace std 从理论上来说也是有道理的:因为系统库可能会升级,这样升级编译使用的 C++ 版本的时候有可能因为引入了新的符号跟自己代码里的命名冲突。


但一般来说,升级 C++ 版本最多几年也就做一次,冲突的可能性也并不大,而升级 C++ 版本本来也不一定能保证编译成功,为了这种特殊时候省一点时间让平时的编码和阅读都变费劲并没有什么道理。


B:

其实底线就一条:如果你的头文件(*.h、*.hpp)有被外部使用,则不要使用任何 using 语句引入其他命名空间或其他命名空间中的标识符。


因为这可能会给使用你的头文件的人添麻烦。更何况头文件之间都是相互套的,假如人人都在头文件里包含若干个命名空间,到了第 N 层以后突然出现了一个命名冲突,这得往前回溯多少层才能找到冲突啊。而这个冲突本来是可以避免的。


其实在源文件(*.cpp)里面怎么 using 都是没关系的,因为 cpp 里的代码不影响到他人。甚至如果你的头文件(*.h、*.hpp)只是自己用,那 using 也是没事的。但为了养成良好的习惯,很多人仍然建议不要随便 using,以防写顺手,届时在共享的头文件里也顺手 using 了,造成人祸。


C:


举一个简单的例子: 我们原来的代码一直没问题,但如果要使用 C++17 标准就报一个错,这个错影响还挺多的。具体原因是,C++17 添加了一种新类似 std::byte ,而 Windows 头文件里自带一种类型 byte


这两种类型本身并不冲突,因为一个是 std::byte,另一个是 byte


但是!!!,如果代码里广泛使用了using namspace std;再遇到 byte 的时候,编译器就不知道它是 Windows 的 byte 还是 std:byte 省略了 std。所以,尽量少在工程里包含这种"大杀器"。你如果想省事,可以在自己的 .cpp 文件里使用(.cpp 不暴露声明)。实在想在 .h 里用(为省事),尽量使用诸如 using std::vector; 之类的,用哪个暴露哪个,而不是一次性全部暴露。


D:


《C++ Primer Plus (第六版 中文版 人民邮电出版社)》第九章: 内存模型和名称空间 第 328 页:

“有关 using 编译命令和 using 声明,需要记住的一点是,他们 增加了名称冲突的可能性。”


《C++ Primer Plus (第六版 中文版 人民邮电出版社)》第九章: 内存模型和名称空间 第329页:


一般说来,使用 using 命令 比 使用 using 编译命令 更 安全 ,这是由于它只导入了制定的名称。

如果该名称与局部名称发生冲突,编译器将发出指示。using 编译命令导入所有的名称,包括可能并不需要的名称。如果与局部名称发生冲突,则 局部名称将覆盖名称空间版本 ,而编译器并不会发出警告。

另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确知道添加了哪些名称。

然而名称空间的支持者希望有更多的选择,既可以使用解析运算符面也可以使用 using 声明,也就是说,不要这样做:


19.png19.png19.png

19.png

而应这样做


20.png


或者这样做

21.png所以,总之:头文件里不要用 using namespace。因为头文件内容相当于一段代码的公开部分,会在预处理阶段被替换进引用者的源文件里。

具体命令操作查看:


22.png


使用 using namespace 会对引用者产生侵入性,使得引用你的头文件有很多未知的副作用。不仅 using namespace,任何 using 都是要尽量避免的。任何类型函数都应该写全名。


如果在源文件中用 using namespace 就是个人的选择了。特别是项目小没有很多重名的时候。如果你看到 Google c++ style guide 上说不要用 using namespace std,更多是因为代码库里有很多 std 的补充替代品,比如 absl。使用时注明用的是哪个可读性比较好。



目录
相关文章
|
Ubuntu Linux Android开发
WireGuard 系列文章(三):WireGuard 安装
WireGuard 系列文章(三):WireGuard 安装
如何解决vscode中文路径的问题
如何解决vscode中文路径的问题
2221 0
|
传感器 并行计算 算法
多传感器感知原理解读 | BEVFusion解读(一)
多传感器感知原理解读 | BEVFusion解读(一)
1769 0
|
Kubernetes 安全 Linux
【阿里云镜像】使用阿里巴巴开源镜像站镜像——Kubernetes 镜像
Kubernetes 是一个开源系统,用于容器化应用的自动部署、扩缩和管理。它将构成应用的容器按逻辑单位进行分组以便于管理和发现。
4052 0
【阿里云镜像】使用阿里巴巴开源镜像站镜像——Kubernetes 镜像
|
安全 网络安全 数据安全/隐私保护
DirectX修复工具增强版,免费的dll修复工具,dll下载,DirectX修复工具下载
DirectX修复工具是一款系统级工具软件,支持Windows XP至Windows 11多个操作系统版本,兼容32位和64位系统。程序可自动调整任务模式,无需用户设置,操作简便,点击即可修复DirectX问题。增强版还支持修复C++运行库问题,提供在线修复版和标准版多种选择。遇到如英雄联盟game_error_directx错误或0xc000007b问题时,使用该工具可有效解决。程序具备扩展功能,可通过下载数据包升级为增强版,并提供详细错误提示与修复方案,适用于多种DirectX及C++异常情况。
5812 4
|
监控 Shell 数据处理
Python执行Shell并获取结果的全面指南
Python执行Shell并获取结果的全面指南
1522 1
|
安全 数据处理 C#
深入理解C#中的Span<T>和Memory<T>
【1月更文挑战第8天】本文旨在探讨C#中引入的两个重要类型:Span<T>和Memory<T>。它们为开发者提供了一种高效且安全的方式来处理内存中的数据。文章首先介绍这两个类型的基本概念和用途,接着深入分析它们的工作原理和适用场景,并通过代码示例展示如何在实际应用中使用它们。
1023 2
|
负载均衡 数据安全/隐私保护 网络架构
理解网络交换机:L2与L3交换机的功能与区别
理解网络交换机:L2与L3交换机的功能与区别
2873 0
腾讯,干掉Redis项目,正式开源Tendis,太牛皮啦
Tendis是腾讯互娱CROS DBA团队 & 腾讯云数据库团队自主设计和研发的分布式高性能KV存储数据库,兼容Redis核心数据结构与接口,可提供大容量、低成本、强持久化的数据库能力,适用于兼容Redis协议、需要大容量且较高访问性能的温冷数据存储场景。