2023-09-07 C++命名空间的一些陷阱


老林的C语言新课, 想快速入门点此 <C 语言编程核心突破>



前言

最近看到个问题, 就是在命名空间中声明一个变量 ( int rand = 0 ), 用using namespace将这个命名空间引入 ( 污染 ) 进全局空间, 当函数调用此变量时发生错误.

这是命名空间全局污染典型案例, 我们进行一些剖析


一、命名空间是什么?(InsCode AI 创作助手)

C++ 命名空间(namespace)是一种将全局作用域分割为若干个小的作用域的机制。

它可以解决命名冲突(name clash)的问题,使不同作用域下的同名标识符互不干扰。

命名空间的使用方法如下:

1.定义命名空间:可以在全局空间下定义命名空间,也可以在已有的命名空间内定义子命名空间,例如:

namespace math
{
    int add(int a, int b)
    {
        return a + b;
    }

    namespace geometry
    {
        double circle_area(double r)
        {
            return 3.14159 * r * r;
        }
    } // namespace geometry
} // namespace math

2.使用命名空间:可以用 using namespaceusing 关键字引入一个或多个命名空间,也可以使用作用域限定符访问命名空间中的标识符。

using namespace math; // 引入 math 命名空间

using math::geometry::circle_area; // 仅引入 math::geometry::circle_area 标识符

int main()
{
    int sum = math::add(1, 2); // 使用作用域限定符访问 math 命名空间中的函数
    double area = circle_area(10.0); // 直接使用 circle_area 标识符(已引入)
    return 0;
}

二、命名空间全局污染

命名空间是一种防止变量和函数因名称重复, 导致程序失败的机制。

全局污染是指太多的变量和函数被定义在全局命名空间中,容易产生命名冲突和互相干扰,从而导致程序出现错误。

通过使用命名空间,可以将变量和函数封装到特定的命名空间中,以避免与其他变量和函数冲突。

这提高了代码的可维护性和可读性,并使代码更易于理解和修改。

但是, 有一种不良的编程习惯, 就是将命名空间引入全局, 导致全局污染的发生.

以下是一个示例, 根据关于c++的命名空间的一个问题的问答代码, 做的修改.

#include <iostream>

namespace hk
{
    int rand = 0;
}

using namespace hk;

auto main() -> int
{
    auto a = rand;
}

代码中, hk作为一个命名空间, 被引入到全局, 然后我们惊讶的发现, 程序中的 rand 发生了冲突, 编译器无法识别, rand究竟是一个int对象还是一个函数指针.

仔细剖析, 发现, rand本身是一个库函数, 当 hk 污染进全局, 作为int对象的 rand 和 函数名 rand 冲突了.

只是我们没有引入过与rand函数相关的头文件, 这个rand又是哪里来的?

这就是C++的要命之处, 头文件的相互引用.

我们只是引入<iostream>, 而它又引用其他头文件, 其他头文件不知引用了多少次之后, 引用了 <stdlib.h> 头文件, 是的, 你无法知道你的实现代码中究竟引用了什么.

这也是为什么, C++的前辈告诉我们, 永远不要使用using namespace将命名空间引入全局的原因, 这与命名空间的初衷背道而驰, 它是用来解决命名冲突问题的, 不是引入命名冲突问题的.

所以, 在偷懒的时候, 一定要知道偷懒可能产生的代价.

为了解决上述问题, 代码不得不改为:

auto main() -> int
{
    auto a = hk::rand;
    auto b = ::rand;
}

总结

有时候, 前人总结的经验不一定立刻起到作用, 比如, 绝对不要人为引入全局空间污染,

但当你违背以上警告, 却没有产生问题, 还貌似提高了打字效率,

殊不知, 各种莫名奇妙的bug就在路上等着, 你可能害了整个团队, 让一个下游程序员莫名奇妙的追踪数百乃至数万个编译报错, 蹂躏并撕扯下他本就所剩无几的头发.


老林的C语言新课, 想快速入门点此 <C 语言编程核心突破>


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不停感叹的老林_<C 语言编程核心突破>

不打赏的人, 看完也学不会.

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值