罗剑锋的C++实战笔记
罗剑锋
奇虎360技术专家,Nginx/OpenResty开源项目贡献者
立即订阅
3724 人已学习
课程目录
已完结 30 讲
0/4登录后,你可以任选4讲全文学习。
课前导读 (2讲)
开篇词 | 把C++从“神坛”上拉下来,这次咱这么学
免费
课前准备 | 搭建实验环境
概论 (5讲)
01 | 重新认识C++:生命周期和编程范式
02 | 编码阶段能做什么:秀出好的code style
03 | 预处理阶段能做什么:宏定义和条件编译
04 | 编译阶段能做什么:属性和静态断言
05 | 面向对象编程:怎样才能写出一个“好”的类?
语言特性 (5讲)
06 | auto/decltype:为什么要有自动类型推导?
07 | const/volatile/mutable:常量/变量究竟是怎么回事?
08 | smart_ptr:智能指针到底“智能”在哪里?
09 | exception:怎样才能用好异常?
10 | lambda:函数式编程带来了什么?
标准库 (4讲)
11 | 一枝独秀的字符串:C++也能处理文本?
12 | 三分天下的容器:恰当选择,事半功倍
13 | 五花八门的算法:不要再手写for循环了
14 | 十面埋伏的并发:多线程真的很难吗?
技能进阶 (4讲)
15 | 序列化:简单通用的数据交换格式有哪些?
16 | 网络通信:我不想写原生Socket
17 | 脚本语言:搭建高性能的混合系统
18 | 性能分析:找出程序的瓶颈
总结篇 (5讲)
19 | 设计模式(上):C++与设计模式有啥关系?
20 | 设计模式(下):C++是怎么应用设计模式的?
21 | 知识串讲(上):带你开发一个书店应用
22 | 知识串讲(下):带你开发一个书店应用
期末测试 | 这些C++核心知识,你都掌握了吗?
结束语 (1讲)
结束语 | 路远,未有穷期
轻松话题 (4讲)
轻松话题(一) | 4本值得一读再读的经典好书
轻松话题(二) | 给你分享我的工作百宝箱
轻松话题(三) | 提高生活质量的App
轻松话题(四) | 真正高效的生活,是张弛有度
罗剑锋的C++实战笔记
15
15
1.0x
00:00/00:00
登录|注册

06 | auto/decltype:为什么要有自动类型推导?

罗剑锋 2020-05-19
你好,我是 Chrono。
前两周我们从宏观的层面上重新认识了 C++,从今天开始,我们将进入一个新的“语言特性”单元,“下沉”到微观的层面去观察 C++,一起去见一些老朋友、新面孔,比如 const、exception、lambda。
这次要说的,就是 C++11 里引入的一个很重要的语言特性:自动类型推导。

自动类型推导

如果你有过一些 C++ 的编程经验,了解过 C++11,那就一定听说过“自动类型推导”(auto type deduction)。
它其实是一个非常“老”的特性,C++ 之父 Bjarne Stroustrup(B·S ) 早在 C++ 诞生之初就设计并实现了它,但因为与早期 C 语言的语义有冲突,所以被“雪藏”了近三十年。直到 C99 消除了兼容性问题,C++11 才让它再度登场亮相。
那为什么要重新引入这个“老特性”呢?为什么非要有“自动类型推导”呢?
我觉得,你可以先从字面上去理解,把这个词分解成三个部分:“自动”“类型”和“推导”。
“自动”就是让计算机去做,而不是人去做,相对的是“手动”。
“类型”指的是操作目标,出来的是编译阶段的类型,而不是数值。
“推导”就是演算、运算,把隐含的值给算出来。
好,我们来看一看“自动类型推导”之外的其他几种排列组合,通过对比的方式来帮你理解它。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《罗剑锋的C++实战笔记》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(20)

  • Mervin
    课后题:
    1. 给程序作者带来了一些便利,但是给读者比较大的麻烦,所以我认为尽量还是应该在比较清晰明确的地方使用,并加以明确的注释。
    2.auto推导的是编译器计算变量初始值得到类型的,decltype也是分析表达式但是不需要计算表达式,所以它与表达式本身有很大关系。

    作者回复:
    1.说的很好,所以要用好auto还是要掌握一个度。

    2.auto和decltype的编译期计算类型过程是一样的,都是得出类型,不会计算表达式,只是一个从初始化里获取表达式,一个自带表达式,这个区别导致了用法的不同。

    2020-05-19
    3
  • EncodedStar
    我觉得auto 虽然方便了,但是代码不能都用auto吧,大量的auto反而让程序员摸不着头脑,这就像看一本书所有地方都花下划线就失去了下划线的意义。
    auto对于减少冗赘的代码也很有用。比如:之前我们写代码是:
    for(vector<int>::const_iterator itr = m_vector.begin(); itr != m_vector.end();++itr)
    可以使用auto简化为:
    for(auto itr = m_vector.begin(); itr != m_vector.end();++itr)这样写就简单多了。
    所有的功能都是建立在好的方向发展的,所有的功能都是工具,工具只有利用对了才是好的,怎么能利用好这时候就看使用者的功底和经验丰富程度了。

    decltype 和 auto 一起使用会更为有用。auto 变量的类型只有编译器知道,而 decltype 对于大量运用运算符重载和特化的类型的代码的表示也非常有用。

    作者回复: 如果觉得auto太多,可以先试着用它来简化复杂类型的声明,然后再慢慢扩展应用场合。

    decltype在泛型编程和模板元编程里非常有用。

    2020-05-19
    1
    2
  • Geek_197dc8
    auto总是推导出“值类型”,但绝不会是“引用”,这句话怎么理解,难道不可以推导出引用的类型嘛?我看你的例子 auto& x1=x,不是推导出引用类型嘛。

    作者回复: 注意细看,auto还是值类型,而“auto&”才是引用类型。

    2020-05-21
    1
    1
  • Jason
    "auto 和 decltype 虽然很方便,但用多了也确实会“隐藏”真正的类型,增加阅读时的理解难度。"
    我觉得这很算缺点,它们应该只用在确实很难手动推导出变量类型的地方。

    作者回复: 对,所以auto不宜用的太多,要适当,最好能够加一下注释,说一下这个auto是什么。

    2020-05-19
    2
    1
  • 鲁滨逊
    没看明白这里:
    auto* x2 = &x; // auto推导为long,x2是long*
    const auto& x3 = x; // auto推导为long,x3是const long&
    auto x4 = &x3; // auto推导为const long*,x4是const long*
    都是&x,x2的auto推导为long,x4的auto却是long*呢?看到这种问题就意识到自己基础不好了

    作者回复: 注意看auto有没有修饰符。

    x2是auto*,那么auto就不会再推导出指针了,而x4是auto,没有修饰,所以auto就是指针类型。

    2020-06-07
  • 陈英桂
    就像python的变量的数据类型随时可以改变,根据右值推导出来,这样代码可读性很差。

    作者回复: 加上一点注释,就可以让auto对人类友好很多。

    2020-06-03
  • 陈英桂
    用auto和decltype给写代码的带来一些便捷性,但是会降低代码的可读性,给维护者的阅读带来一些障碍。
    对于迭代器,可以用auto来简化代码,尽量不要用在函数的返回值和入参。

    作者回复: 这个还是看个人了,我觉得auto可以简化复杂类型的书写,比手写类型会更正确,需要在可读性和效率间取一个适当的折中。

    2020-06-03
  • 下雨天
    decltype(auto) x1 = (x); // 推导为int&,因为(expr)是引用类型。老师,这里为什么是引用?x不是值吗?

    作者回复: 这里是C++一个比较奇怪的语法,x是值类型,加上括号就变成了引用类型,算是个“坑”吧。

    不建议去了解这个细节,可能会更迷惑,最好不要这么用,这里我只是为了举例。

    2020-06-01
  • 九三
    老师, 总是在一些c++ 源码看到extern “C” 对这个关键字理解的不是很透

    作者回复: 这个是为了兼容C语言,因为C++编译生成的链接符号与C不一样,用这个就会导出与C一样规则的符号,方便外部库调用。

    可以再搜一下相关的资料,看几篇就能理解了。

    2020-05-30
  • yelin
    2.
    推导规则:auto值总是值类型,decltype 不仅能够推导出值类型,还能够推导出引用类型。&,*,const的属性也会被decltype取得
    应用场景:auto除了不能在定义类时使用,还有一种不关心具体类型的目的在range-based for的场景尤其明显,在;decltype则没有义类的使用限制,decltype会尤其关心具体的类型值,推导计算得到后才会返回

    作者回复: 总结的挺好。

    2020-05-27
  • yelin
    1. 类型推导用起来方便,代码里都用auto的话,那个感觉应该和python是一样的吧,所以不知道有没有好的解决方案,我在python里的习惯是在命名加前缀,还有就是注释了吧,如果是协作开发的模块,auto我一般也就是用来内部遍历/range-based for之类的场景。请教下老师,还有没有更好的办法。

    作者回复: 如果是用惯了Python等动态语言,可能会对auto很适应。

    但毕竟C++是强类型语言,如果不小心推导出了你不需要的类型就会很麻烦,所以为了“给人看”,对于不是那么能够一眼看出来的类型,最好还是注释说明一下。

    2020-05-27
  • 湟水鱼儿
    公司编码不支持auto,只有自己私下里用一用,过一过瘾

    作者回复: 唉,这个也是没办法的事情,以前我用的环境是gcc4.4,C++11支持不完整,非常痛苦。

    2020-05-25
  • 汪zZ
    看auto的时候,省略了一下,觉得我这个初学者应该知道它存在就可以了,
    结果发现真的,有它更开心。

    作者回复: 这就是C++的哲学:自由,你怎么做都可以,总可以找到自己喜欢的风格。

    2020-05-23
  • silverhawk
    我说一个这种自动推导的隐藏代价吧,不是C++里面,C#里面的Var,有一次遇到一个Var res = func(),这个func()返回一个Ienumerable,但是这个var就掩盖了这个Ienumerable究竟是List,还是其他什么,实际上背后有个stream的实现,之后程序中多次出现foreach res,其实就是多次遍历了这个stream,凭空增加了overhead。如果能够在写的时候显示定义,可能会想的更清楚,写出性能更高的

    作者回复: 对,对于某些很重要的类型,用auto后最好用注释说明它是个什么,后续该怎么用,否则会导致后面的代码比较难懂。

    2020-05-23
  • 禾桃
    int x;
    auto * y = &x; // auto 被推倒成int, y的类型是int*
    auto z = &x; // auto 被推倒成int *, z的类型也是int*

    请问是这样吗?
    如果是的话,是不是意味着如果我们知道右边是个指针类型,就直接用 auto w = 表达式,而不是auto * w =表达式?

    谢谢

    作者回复: 理解的很对。

    auto还是比较智能的,会自动推导出正确的类型,注意它一定是值类型,不会是引用。

    2020-05-21
    2
  • Zivon
    auto 和 decltype 虽然很方便,但用多了也确实会“隐藏”真正的类型,增加阅读时的理解难度,
    确实有这方面的影响,再看自己过去写的代码,auto会减慢阅读速度,但IDE能提供一些辅助会好些。
     auto 和 decltype 的区别。decltype能实现精确推导,auto一定不会推导出引用类型。另,再类内auto不可使用。

    作者回复: 说的很好,auto配合适当的注释就比较完美了。

    2020-05-21
  • Luke
    C++14 auto用于推到函数返回值,个人觉得是鸡肋,增加代码阅读难度,本来忘了返回值类型,看一眼函数头就行了,现在还得去看函数体具体的返回值类型到底是什么。这是为了迎合python程序员转C++么😂

    作者回复: C++会给我们多种选择,我们也可以选择不用,这个特性在写泛型函数的时候会很方便。

    另外auto还可以用在返回值类型后置的用法,有的特别的模板函数就真的只能这么写了。

    2020-05-21
  • 中年男子
    auto, decltype 用起来很方便,
    说来惭愧,以前一直很烦写函数指针的声明,每次不得不写的时候都得google 一下,
    自从用了decltype 再也不用担心了

    auto 自动类型推导,我最多的应用场景就是用来声明 stl的迭代器,能少敲键盘,range-based for 实践也能简化代码, 使代码看起来更明了,文中说的 避免了类型的“硬编码”, 在实际工作中我碰到这种情况的时候比较少, 也没注意。也是个最佳实践了。

    作者回复: auto和decltype用得少体会不出优越性,只有写得多了,在比较复杂的泛型场景下,就会发现很多时候必须得用这两个关键字。

    2020-05-20
  • lckfa李钊
    我倒是觉得auto可以多用啊,隐藏的真正类型完全可以使用vscode的cpp插件或者ide工具直接查看到,不算大的缺点。如果要说C ++11让我最舒服的地方就是auto和using了。

    作者回复: 我也比较同意,auto和using能很大程度改善代码。

    2020-05-19
  • 范闲
    1. 大量使用auto和delctype确实会有这种问题。所以产量定义和初始化的时候原类型定义还是不错的.auto其实循环展开上用比较合理。delctype在类定义里使用,不传递到外部。
    2.auto和delctype其实更多是语法糖的效果。实际类型确定都在编译期。

    作者回复:
    1.auto还可以用在复杂的模板类定义的时候,比如容器的迭代器。

    2.delctype可不能单纯地认为是语法糖,它是编译期计算,在泛型编程和模板元编程的时候非常有用,像nullptr的类型,就是用了decltype。

    2020-05-19
收起评论
20
返回
顶部