前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >技术◈C++核心知识总结(I)

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

作者头像
leoay
发布于 2019-12-27 03:04:46
发布于 2019-12-27 03:04:46
76600
代码可运行
举报
文章被收录于专栏:leoayleoay
运行总次数:0
代码可运行

这是leoay的第2篇长文分享

图:leoay

上篇文章,我写了一下自己对写作这件事的浅解,也是我第一篇超过两千字的长文。接下来,我想写一系列关于C++11核心知识的总结文章。有的朋友可能觉得我飘了,竟然敢写C++(作为一门高冷的语言,就是叼)!。。。没错,我就是飘了!我就敢写!

哈哈,开个玩笑了,写确实是敢写,不过写得好与坏就另当别论了,先不管好坏,我认真写,你们随心看,有写得不好的地方欢迎留言区批评,指正!如果觉得不错的话,欢迎分享转发!

首先需要说明的是,虽然这是一系列关于C++核心知识的总结,但是并不等同于一个完整的C++教程,所以想完全依赖我这几篇文章学透C++,我只能告诉你,休想。这几篇文章仅仅梳理C++中比较重要的核心知识点(工作或面试),如果没有C/C++基础的同学,可以自行弥补,文末我会推荐几本C/C++相关书籍!

作为第一篇文章,当然将一些比较基础的概念,以下(高手略过):

(1)自动类型推导 auto & decltype()

(2)常量限定符 const & constexpr

(3) 空指针 null 与 nullptr

这一篇文章很基础,如果对以上三点能快速说出其用法及需要注意的细节,那么下面的就可以忽略了

好了,先不BB了,下面开始说正事儿:

1. 自动类型推导 auto & decltype()

关于类型可能很多同学会觉得这个话题比较简单,因为这基本是所有语言的基础,C/C++、Java等等这些静态类型语言...,基本都放在第一章节讲解,而且很多语言是相通的,但是C++有一个比较强大的关键字auto,我觉得有必要强调一下。其实,我们可以根据这个词的意思差不多猜出这个关键字的功能 —— 自动类型推导。也就是说如果一个变量的类型是auto时,它会根据变量的值自动推导出类型。那么,可能就会有朋友产生疑问了:变量是什么类型不是很容易看出来吗?感觉没什么用处。也许在C语言或Java中,确实,变量的类型清晰可见,但是C++就不一样了。例如,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<class T, class U>
auto add(T t, U u) { return t + u; }

C++中有模板的概念,代码中所示模板就是实现两个对象t和u的加法,当我们调用add函数时,由于使用了auto关键字,返回值类型会自动推导,即为t+u结果类型,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
auto  b = add(2, 5);     //这里的b是int型
auto  c = add(2.3, 8);    //这里的c是float型

到这里,可能又有朋友说,这也没什么呀,我还是能一眼看出结果的类型,但是这里因为有了auto,才更加体现了C++模板的优势,定义一次函数,就可以进行多种类型数据的运算处理,并可以返回不同类型的结果,实现代码的复用。那么,除了这种比较简单的情况,还有没有比较复杂的类型?下面接着看:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vector<vector<Dtype> > pred_boxes;
for (auto pred_box = pred_boxes.begin(); pred_box != pred_boxes.end(); pred_box++)
{
  pred_box->push_back(batch_id);
}

这是我从caffe框架中截取的一段代码,先不管其含义,仅仅关注auto的用法。这里是实现一个遍历的功能,将batch_id存到pred_box中。我们定义了一个迭代器pred_box,这里由于auto会自动推导其类型,我们几乎什么都不用管。但是实际上它的类型是什么样的呢?请看:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vector<vector<Dtype> >::iterator pred_box;

就是上面的代码中所写,是不是觉得繁琐了很多。说到遍历,我们也可以将上面的代码这样简化:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vector<vector<Dtype> > pred_boxes;
for (auto pred_box :pred_boxes)
{
  pred_box->push_back(batch_id);
}

世界又清净了一些!

说完auto,C++中还有一个与自动类型获取有关的关键字 —— decltype。 那么这二者有什么区别呢?auto关键字根据表达式的值推导其类型,可以假想为auto变成了这个类型(实际上不是)。在这个过程中表达式是会被计算的,但是有时候我们并不想表达式被计算,但是仍然希望得到表达式值的类型,这就用到了decltype,用法就是decltype(表达式),举个栗子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
decltype(pred_boxes) pred_boxes1;

我们定义一个和pred_boxes类型的相同的变量pred_boxes1

同样,对于下面的表达式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int &k = 1;
decltype(k)  j = 1;

j的类型就是int引用类型了。

2. 常量限定符const与 constexpr

讲完了自动类型推导,接下来说一下C++中与常量定义相关的两个关键词 const 和 constexpr。

首先它们都是限定符,起到对变量进行限定的作用,当我们不希望一个变量的值被修改时,我们就需要用const进行限定。比如我们希望固定一个缓冲区的大小:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const int bufferSize = 1024;

那么,这里bufferSize便为不可修改变量,这里的用法与在C中一样,下面讲一下const在C++中的用法。

(1)const的用法

const与引用一起使用

在C++中const会经常与引用一起使用,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const int i = 512;
const int &j = i;

这里i与j都是常量,i是整型常量,就是整型引用常量(指向常量的引用),而且需要注意一点,const常量只能作为const常量的值(有点拗口!)

举个例子:

这里j是一个指向常量的引用,它也可以作为一个值,初始化另一个常量如下

const int &k = j;

这里k如果是一个引用的话必须为常量,如果不是引用的话,可是是一个变量。如下:

int k = j;

可能有的朋友会有些疑惑,既然

int &k = j;

不可以,为什么去掉&就可以了呢?简单解释一下,其实引用并不是一个实体对象,而是代表了一种绑定关系。

对于

int &k = j;

来说,其含义是将k绑定到j, 虽然k和j名字不同,但是在硬件上,它们占用同一块内存,既然j是常量,那么k必然是常量,而

int k = j;

就不一样了

const与指针一起使用

除了与引用在一起鬼混,const还常常喜欢与指针一起玩耍。这里先简单说一下引用和指针的区别,虽然很简单,但是我觉得还是有必要略讲一下。上面谈到引用其实并不是一个实体对象,即不像整型变量、结构体、枚举等等这些变量独自占据内存空间,引用表示了一种绑定关系,将一个别名绑定到一块内存空间(所以定义引用变量时必须要初始化)。但是指针就不同了,本质上,指针是一块存储内存地址的变量,它有一块内存空间存储地址信息。那么const与指针一起使用,又会发生什么有意思的事呢?一起来看几个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const double pi = 3.14;
const double *ptr  = &pi;

ptr是一个指向const double类型的指针,所以其值必须为const double类型的地址,这里只需要保证指针指向的值不变即可,至于ptr中存的值(地址)是可以改变的,也就是说这里的const限定了指针指向的内存存的值,即上面pi不可改变。

上面说过,指针本身也是一个实体对象,不像引用徒有虚名。所以有一个叫常量指针的(const pointer)家伙。既然叫常量指针,const限定的是指针本身,这就意味着指针中的值不可改变,举个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
double pi = 3.14;
double * const ptr = &pi;

ptr中的值在其生命周期中永远指向&pi, 此时pi可以随意改变,但是ptr中存的地址是固定的。

那么将这两者结合起来就可以得到

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const double pi = 3.14;
const double * const ptr = &pi;

这样ptr无论指向的值还是其本身都是不可以改变的。

const与类的成员函数一起使用

const除了与“变量”一起使用外,在C++中还会与类的成员函数一起用。这个涉及到类与对象相关的知识,还有成员函数,成员变量,展开讲的话会比较多,后面与类和对象放一起说。

(2)constexpr的用法

上面我们讲了讲const的用法,下面就简单说下constexpr。constexpr作为限定词在含义上与const并不相同,constexpr是为了在初始化一个变量时,让编译器判断这个变量的值是否是一个常量或常量表达式,如果该变量用constexpr限定,但是初始化值并不是一个常量或者常量表达式,编译器便会报错,(因为我们在定义常量时并不确定右边的表达式是否是常量表达式),这样看来还是难于解释,下面就用几个例子解释一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
constexpr int a = k +1;
constexpr int b = newfun();

在这两个例子中,编译器在编译时会检查k+1和newfun()是否是常量表达式(函数),如果不是,上面的定义就不成立,编译会失败。

常量表达式一个重要的特点就是在编译阶段已经确定,下面这个就不是常量表达式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const int b = newfunc();

因为,这里newfunc()在程序运行的时候才知道结果,在编译阶段因为没有用constexpr限定,编译器并不会检查newfunc()

前面我们说了指针和引用,这里constexpr也是可以和它们一起使用的,但是限制地比较严格。以下用指针举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const int *i = nullptr;
constexpr int *i = nullptr;

第一个i表示指向int常量的指针

第二个表示指向int的常量指针

3. 空指针NULL与nullptr

下面说一下C++中的空指针。熟悉C的朋友对空指针非常熟悉,NULL。对,C++中仍然有这个关键字,不信可以看上面的关键字表。但是,在标准C++不建议使用NILL,因为NULL是整数0的宏定义。我们经常使用空指针来初始化一个指针变量,试想一下如果用一个整数作为指针变量的值,总是有些不妥,尽管编译器不会报错。所以C++11标准推荐我们使用nullptr,这个关键字本身就是代表空指针,更加合适,所以下次如果你们在C++中初始化一个指针变量时,就用名副其实的nullptr吧。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 leoay 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
c++ primer2 变量和基本类型。
这四种初始化方式c++11都是支持的。c++11中用花括号来初始化变量得到了全面应用。
和蔼的zhxing
2018/09/04
5410
Modern c++快速浅析
•template<typename T> void func(T& param);在这个示例函数中,如果传递进是一个const int&的对象,那么T推导出来的类型是const int,param的类型是const int&。可见引用性在型别推导的过程中被忽略•template<typename T> void func(T param);在这个示例函数中,我们面临的是值传递的情景,如果传递进的是一个const int&的对象,那么T和param推导出来的类型都是int如果传递进的是一个const char* const的指针,那么T和param推导出来的类型都是const char*,顶层const被忽略。因为这是一个拷贝指针的操作,因此保留原指针的不可更改指向性并没有太大的意义
高性能架构探索
2024/01/03
2260
Modern c++快速浅析
C++11基础学习系列一
---- 概述 C++11标准越来越趋于稳定和成熟,国外c++11如火如荼而国内却依然处于观望期。每当提到C++很多程序员都很抵触,特别是学术界的呼声更高一些。其实不然,语言即工具,语言的好坏不在于本身,而在于驾驭它和适用它所在的范围所决定的。那么为什么国内大多数程序员都会遭到抵触呢?我觉得原因有如下(不要劈我,仅此个人意见): C++是对C语言进行了抽象同时又支持了很多面向对象的特性,在趋于底层设计时又对上层进行封装和扩展。它是从计算机科学层面去设计和演化的,如果想写出高效和稳定的程序,那么你就必须具备基
吕海峰
2018/04/03
9320
C++11基础学习系列一
C++11——引入的新关键字
auto是旧关键字,在C++11之前,auto用来声明自动变量,表明变量存储在栈,很少使用。在C++11中被赋予了新的含义和作用,用于类型推断。
恋喵大鲤鱼
2018/08/03
1.5K0
C++ 的发展
C++ 是由 Bjarne Stroustrup 于 1979 年在贝尔实验室(Bell Labs)开始开发的,最初是作为 C 语言的一个扩展,目的是在不丧失 C 语言高效性的基础上,提供面向对象编程的特性。C++ 的发展历程可以分为以下几个重要阶段:
ljw695
2024/11/15
6730
C++ 的发展
C++11新关键字
auto是旧关键字,在C++11之前,auto用来声明自动变量,表明变量存储在栈,很少使用。在C++11中被赋予了新的含义和作用,用于类型推断。
恋喵大鲤鱼
2019/02/22
3.1K0
《Effective Modren C++》 进阶学习(上)
  作为一名有追求的程序猿,一定是希望自己写出的是最完美的、无可挑剔的代码。那完美的标准是什么,我想不同的设计师都会有自己的一套标准。而在实际编码中,如何将个人的标准愈发完善,愈发得到同事的认可,一定需要不断积累。如何积累,一定是从细微处着手,观摩优秀的代码,学习现有的框架,汲取前人留下的智慧。
开源519
2023/11/15
2270
《Effective Modren C++》 进阶学习(上)
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
但是到了c++11实现了可以用{}对容器进行一些初始化等,比如push/inset多参数构造的对象时,{}初始化会很⽅便,这是因为每个类型它都会有个initializer_list的一个构造,这样就方便了我们操作。
用户11458826
2025/01/23
350
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
c++基础之变量和基本类型
之前我写过一系列的c/c++ 从汇编上解释它如何实现的博文。从汇编层面上看,确实c/c++的执行过程很清晰,甚至有的地方可以做相关优化。而c++有的地方就只是一个语法糖,或者说并没有转化到汇编中,而是直接在编译阶段做一个语法检查就完了。并没有生成汇编代码。也就是说之前写的c/c++不能涵盖它们的全部内容。而且抽象层次太低,在应用上很少会考虑它的汇编实现。而且从c++11开始,加入了很多新特性,给人的感觉就好像是一们新的编程语言一样。对于这块内容,我觉得自己的知识还是有欠缺了,因此我决定近期重新翻一翻很早以前买的《c++ primer》 学习一下,并整理学习笔记
Masimaro
2021/01/20
1.6K1
【笔记】《C++Primer》—— 第2章
这本书真是可怕,越看才越是知道自己欠缺的东西是有多么多...第二章又看到了很多不明白的东西,还有一些C11才带来的全新的概念,结果这篇可能会稍长一点,好多东西值得慢慢消化呢。
ZifengHuang
2020/07/29
5480
【笔记】《C++Primer》—— 第2章
c++从入门到进阶--引用与常量
constexpr必须用常量表达式初始化,也就是说必须在编译过程就能计算出结果(若要用函数作为constexpr的初始值那么该函数应该是constexpr类型的函数)。
风骨散人Chiam
2020/10/28
8080
Effective Modern C++翻译(2)-条款1:明白模板类型推导
第一章 类型推导 C++98有一套单一的类型推导的规则:用来推导函数模板,C++11轻微的修改了这些规则并且增加了两个,一个用于auto,一个用于decltype,接着C++14扩展了auto和decltype可以使用的语境,类型推导的普遍应用将程序员从必须拼写那些显然的,多余的类型的暴政中解放了出来,它使得C++开发的软件更有弹性,因为在某处改变一个类型会自动的通过类型推导传播到其他的地方。 然而,它可能使产生的代码更难观察,因为编译器推导出的类型可能不像我们想的那样显而易见。 想要在现代C++中进行有效
magicsoar
2018/02/06
8010
C++中变量声明与定义的规则
为了支持分离式编译,C++将定义和声明区分开。其中声明规定了变量的类型和名字,定义除此功能外还会申请存储空间并可能为变量赋一个初始值。
TOMOCAT
2021/04/20
2.4K0
c++11新特性,所有知识点都在这了!
本文基本上涵盖了c++11的所有新特性,并有详细代码介绍其用法,对关键知识点做了深入分析,对重要的知识点我单独写了相关文章并附上了相关链接,我整理了完备的c++新特性脑图(由于图片太大,我没有放在文章里,同学可以在后台回复消息“新特性”,即可下载完整图片)。
公众号guangcity
2020/11/10
21K10
c++11新特性,所有知识点都在这了!
C++11新特性学习笔记
C++11标准为C++编程语言的第三个官方标准,正式名叫ISO/IEC 14882:2011 - Information technology – Programming languages – C++。在正式标准发布前,原名C++0x。它将取代C++标准第二版ISO/IEC 14882:2003 - Programming languages – C++成为C++语言新标准。
CtrlX
2023/03/13
2.3K0
C++11新特性学习笔记
『C++』我想学C++,C++太难了,那我想入门,给我10分钟我带你入门
就是一条预处理命令, 它的作用是通知C++编译系统在对C++程序进行正式编译之前需做一些预处理工作,导入头文件下的函数,与类。
风骨散人Chiam
2020/10/28
1.6K0
每个C++开发者都应该学习和使用的C++11特性
Hi,大家好!本文讨论了所有开发人员都应该学习和使用的一系列 C++11特性。该语言和标准库中有很多新增功能,本文只是触及了皮毛。但是,我相信其中一些新功能应该成为所有C++开发人员的日常工作。
Linux兵工厂
2024/03/21
940
每个C++开发者都应该学习和使用的C++11特性
C++ 11 新特性
nullptr\text{nullptr}nullptr 的出现是为了取代 NULL\text{NULL}NULL,避免 NULL\text{NULL}NULL 的二义性。
f_zyj
2019/05/27
7760
C++20新特性个人总结
concept乃重头戏之一,用于模板库的开发。功能类似于C#的泛型约束,但是比C#泛型约束更为强大。
用户7886150
2021/02/04
2K0
C++入门知识(二)
用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。
海盗船长
2020/08/27
5470
相关推荐
c++ primer2 变量和基本类型。
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文