专栏首页leoay技术◈C++核心知识总结(II)

技术◈C++核心知识总结(II)

这是leoay的第3篇长文分享,共计2401字

这是一系列关于C++核心知识总结与分享的文章,如果你没有看过之前的文章,可以先看一下,链接在下面:

C++核心知识总结(I)

废话不多说,直奔主题。这篇文章我主要想分享一下和下面几个概念相关的知识点:

(1)命名空间namespace

(2)string类及字符的处理方法

(3)动态数组vector

(4)左值与右值

1. 命名空间namespace

使用过C++的朋友一定听说过命名空间吧。是的,就是你经常看到的namespace, 虽然大多数同学都会用namespace, 但是只有少部分非常清楚namespace的作用。

下面,我就来简单总结一下吧。命名空间是1995年引入标准C++(ANSIC++)中的, 那么为什么要引入这么一个概念呢?

先讲个故事: 同一个班级中有两个相同名字的同学,比如都叫A, 那么如果老师喊A的时候,就会导致冲突,不知道是哪个A应该答应。这个时候老师为了把这两个同学区分开,就会重新给他们取个名字,分别叫BA和CA, 来避免名字冲突的问题,其实在C++也是如此。

命名空间最重要的作用就是避免程序中的命名冲突问题。

我们在给代码中的类或对象取名字时,很可能会遇到同名的情况,有的朋友可能觉得自己的代码自己很熟悉,怎么可能同名?

是的,如果这个工程的作者只有你自己的话,同名的可能性确实比较小,但是在工作中我们接触到的项目往往非常庞大,项目组成员可能涉及十几人,几十人甚至上百人不等(某些开源项目,作者可能上千人),在这种情况下很难保证代码中命名不冲突。

还有一种命名冲突的情况是两个独立的模块,但是有相同功能的函数,或变量,当我们的项目同时引用这两个模块同名对象时,编译器便不知道该用哪一个模块里面的对象了。

因此,引入命名空间的概念是非常合理且必要的事情。

形象点儿讲,namespace就像工程中的栅栏,把相关的代码(类,对象,函数,变量...)圈起来,这些namesapce 圈圈就相互独立,互不影响,各玩各的。画风就像下面:

说了这么多,那么namespace该怎么用呢?请看下面:

#include<iostream>
using namespace std;
int main()
{
    cout << "Hello World!" << endl;
}

这里,我们还是以通俗易懂、简单友好的的Hello World为例。std就是C++标准命名空间。如果你不想带上它,那么cout标准输出就用不了,因为他们被锁进了std这个圈里了,在其他地方是没有办法访问的。

如果非要用,那么代码的画风就变成下面这样的了,使用一个范围操作符 "::", 表示要使用std中的cout进行输出

#include<iostream>
int main()
{
    std::cout << "Hello World!" << std::endl;
}

看到了吗,cout要想出std这个圈,就必须带上std这个钥匙,对于其他模块同样的道理。在日常项目中,我们还常常会用到boost库,那么代码中就需要boost这把钥匙:

using namespace boost;

或者

boost::xx

命名空间相当于圈定一个作用域,如果希望在某个作用域中使用另一个作用域的对象,便要使用using导入该对象所在命名空间,或者在这个对象前面加上该命名空间的名称。

这样看来似乎非常简单,确实,简单在代码中加上命名空间就好了,如果真是如此,我也没有比较写这个话题了,但是细看的话,还是能发现一些坑和一些小技巧的。

(1)using虽好,不要用在头文件中

最近在看同事写的代码时发现有几处在头文件中使用using的情况,虽然在代码前面简单粗暴地用using一下子导入整个命名空间,快速解决问题。

但是,我们在开发的时候一个头文件可能被很多个模块引用(我们的头文件供其他的人使用,我们很难确定别人会用在哪些地方),如果头文件中直接用using,很容易引起命名冲突的问题,所以为了降低debug的痛苦,建议不要在头文件中使用using!

(2)避免大范围使用using

这个还是为了降低命名冲突的风险。

如果我们只是想用某个命名空间的某个对象时,在用using引入命名空间时,最好具体到这个对象所在的最小范围命名空间。比如我要使用string,cin, cout,就可以这样写:

using std::string;
using std::cin;
using std::cout;

这里string就是std的子命名空间,大大缩小了命名空间范围。

当然,大多数情况下我们会在代码中直接使用这样的形式(命名空间名加上范围操作符加上):

void func(){
    std::cin ...;
    std::string...;
    std::cout...;
}

上面说了那么多都是在讲怎么导入别人的命名空间,下面说一下怎么定义我们自己的命名空间。

其实也很简单,就是去掉using,如下:

namespace 命名空间名{
    表达式1;
    ...
    ...
    表达式2;
}

当然,我们也可以对命名空间进行嵌套操作:

namespace 命名空间名1{
    ...
    namespace 命名空间名2{
    ...
    }
}

那么,命名空间名是唯一的吗?或者说必须要有命名空间名,答案是:否

namespace 命名空间名3 = 命名空间名1; //命名空间1等价于命名空间3
//匿名命名空间
namespace{
    ......
}

上面命名空间3等价于命名空间1相当于给命名空间1取了一个别名,因为有的时候我们会遇到比较冗长的命名空间名,为了避免 繁琐,可以用一个简短的名字替代。

除此之外,上面还有个匿名命名空间的例子,那么这个有什么用呢?

像上面,匿名命名空间形如:

namespace{
    const int k = 10;
}

虽然名为匿名,但是编译器在编译这部分代码时,会为它生成一个唯一的名字,而且还附加一条using指令,效果如下面的代码所示:

namespace __UNIQUE_NAME_{
    const int k = 10;
}
using namespace __UNIQUE_NAME_;

虽然编译器能给匿名命名空间生成一个特殊的名字,但是这个命名空间对全局是不可见的,只在当前文件中有用,而有名字的命名空间对全局是可见的,全局有效。

这个特点有点像static关键字,被static加持的全局变量,也只能在当前文件中有效。实际上匿名命名空间就是C++用来替代static的,C++新标准推荐使用匿名空间而不推荐static。

好了,文章写到这里差不多该结束了,对于namespace你是不是更加清晰了呢?反正经过这一番梳理,我算法比较熟悉了。虽然用了2000多字梳理,但是关键点只有几个,下面用几句话总结一下这篇文章吧:

1、命名空间主要目的是圈定作用范围,避免命名冲突

2、不要在头文件中使用using引入其他命名空间

3、尽可能缩小引入命名空间范围,做到用什么引入什么

4、可以给命名空间取别名,也可以对命名空间嵌套

5、C++中尽量用匿名命名空间替代static

本文分享自微信公众号 - leoay(leoay_Do),作者:leoay

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++の命名空间namespace

    这是一系列关于C++核心知识总结与分享的文章,如果你没有看过之前的文章,可以先看一下,链接在下面:

    leoay
  • C++のString类

    今天的文章没有按时发布(原定早上7:00),跟大家说个抱歉,由于昨天晚上下班回到家就开始忙着建我们的网站(后续很多学习资源将会同步上去),一忙起来就忽略了时间,...

    leoay
  • C++の表达式(2)

    今天,我们继续接着昨天的说,昨天说到了C++中表达式的左值与右值,由于时间关系就没有详细说完整。今天我们继续补充一下。

    leoay
  • C++の命名空间namespace

    这是一系列关于C++核心知识总结与分享的文章,如果你没有看过之前的文章,可以先看一下,链接在下面:

    leoay
  • python中的命名空间和变量作用域

    namespace,称之为命名空间,是名称和对象之间的映射,通常以字典的形式保存变量名和其所指代的变量值之间的映射关系。

    生信修炼手册
  • python的命名空间

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    于小勇
  • swingbench压测Oracle小记(r12笔记第20天)

    今天抽时间在整理一个关于MySQL和Oracle共同面临的问题,但是它们有着不同的解决方案,就是经典的partial write问题,我也看到网上有很多D...

    jeanron100
  • Go学习者资料必读及后续安排计划

    距离上一篇文章已经一个多月了,在这一个多月的时间里面,做了一些go项目,并且也拿到了几个秋招offer,也完成了实习转正答辩,这一个多月成长还是非常大,今天开始...

    公众号guangcity
  • 快学 Go 语言 第 1 课 —— Hello World

    最初 Go 语言的 Logo 是一只可爱的土拨鼠,土拨鼠昼伏夜出的习性让它显得很有 Geek 范。土拨鼠的行动其实并不敏捷,不过它繁殖能力很强,生长发育的很快。...

    老钱
  • Beego初体验

    最近在学习 Go 语言,并打算用 Go 语言做 web 开发,便开始了 Beego 框架的学习,Beego 是一个使用 Go 的思维来帮助构建并开发 Go 应用...

    枉凝眉

扫码关注云+社区

领取腾讯云代金券