罗剑锋的 C++ 实战笔记
罗剑锋
前奇虎 360 技术专家,Nginx/OpenResty 开源项目贡献者
34779 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 32 讲
结束语 (1讲)
罗剑锋的 C++ 实战笔记
15
15
1.0x
00:00/00:00
登录|注册

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

你好,我是 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/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《罗剑锋的 C++ 实战笔记》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(36)

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

    作者回复: 1.说的很好,所以要用好auto还是要掌握一个度。 2.auto和decltype的编译期计算类型过程是一样的,都是得出类型,不会计算表达式,只是一个从初始化里获取表达式,一个自带表达式,这个区别导致了用法的不同。

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

    作者回复: 这里是C++一个比较奇怪的语法,x是值类型,加上括号就变成了引用类型,算是个“坑”吧。 不建议去了解这个细节,可能会更迷惑,最好不要这么用,这里我只是为了举例。

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

    作者回复: 这个是为了兼容C语言,因为C++编译生成的链接符号与C不一样,用这个就会导出与C一样规则的符号,方便外部库调用。 可以再搜一下相关的资料,看几篇就能理解了。

    2
    11
  • 张飞Dear
    1,算是一个缺点,但是就和容器、条件编译一样,尺有所短寸有所长。用的恰当就好,我现在工作用的的编译器不支持auto,只能自己实验这敲了,用auto 就不用再写那么长的迭代器名称了,很方便。还有使用decltype 来定义迭代器类型 真的是太好用,之前都是用typedef 来进行的。 2,① auto 的“自动推导”能力只能用在“初始化”的场合。不能用在类成员里面初始化。auto 总是推导出“值类型”,绝不会是“引用”。 ② decltype 不仅能够推导出值类型,还能够推导出引用类型,也就是表达式的“原始类型”。可以定义类成员类型。

    作者回复: 总结的很好。 另外说一下,如果用C++11,就应当尽量用using来定义类型别名,少用typedef。

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

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

    2
    6
  • hao
    罗老师,请问下,在函数内部定义了vector,push_back了很多数据,要将这些vector数据作为函数结果返回,也没释放vector,这样会不会有问题?

    作者回复: 不会有问题的。 对于C++11之前,会有rvo返回值优化,把vector拷贝到输出结果。C++11之后会使用转移语义。 无论怎么样,调用函数后都会得到正确的vector结果,内存被新的vector所管理。

    5
  • Geek_ca425d
    JavaScript弱语言类型就是不对类型做定义,运行时推导的,但这种缺点导致开发大型项目的时候各种困难,我觉得主要就是类型不明确锅,所以后来有了typescript这种js超集。前车之鉴,auto还是要少用的。

    作者回复: 不一样,JavaScript是弱类型,而C++是强类型,在编译时会有编译器做检查,auto只是方便了我们的代码编写工作,本质上没有对语言有任何的改变。 当然,对auto有顾虑也是正常的,会感觉少了一些对程序的掌控感,可以慢慢适应。 在现代C++中,由于类型体系越来越复杂,很多地方,不用auto可能根本就写不出来程序,比如lambda表达式。 关键还是要把握一个度,不要滥用,以人类可读、代码可维护为基本尺度。

    4
  • 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在泛型编程和模板元编程里非常有用。

    2
    3
  • X.
    请问老师,for (const auto& i : v) {...}这里,为什么说“常引用方式访问元素,避免拷贝代价” ?为什么不考虑用 for (auto i : v) {...} 呢?

    作者回复: auto是值类型,这里就会对容器里的元素拷贝后再操作,代价就会比较高。 相当于ClassA obj = v[i]

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

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

    2
    2
收起评论
显示
设置
留言
36
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部