通过《C++ auto》和《C++ decltype》两节的学习,相信大家已经掌握了 auto 和 decltype 的语法规则以及使用场景,这节我们将 auto 和 decltype 放在一起,综合对比一下它们的区别,并告诉大家该如何选择。

语法格式的区别

auto 和 decltype 都是 C++11 新增的关键字,都用于自动类型推导,但是它们的语法格式是有区别的,如下所示:

auto varname = value;  //auto的语法格式
decltype(exp) varname [= value];  //decltype的语法格式

其中,varname 表示变量名,value 表示赋给变量的值,exp 表示一个表达式,方括号[ ]表示可有可无。auto 和 decltype 都会自动推导出变量 varname 的类型:

  • auto 根据=右边的初始值 value 推导出变量的类型;

  • decltype 根据 exp 表达式推导出变量的类型,跟=右边的 value 没有关系。

另外,auto 要求变量必须初始化,也就是在定义变量的同时必须给它赋值;而 decltype 不要求,初始化与否都不影响变量的类型。这很容易理解,因为 auto 是根据变量的初始值来推导出变量类型的,如果不初始化,变量的类型也就无法推导了。auto 将变量的类型和初始值绑定在一起,而 decltype 将变量的类型和初始值分开;虽然 auto 的书写更加简洁,但 decltype 的使用更加灵活。请看下面的例子:

auto n1 = 10;decltype(10) n2 = 99;auto url1 = "http://c.biancheng.net/cplus/";decltype(url1) url2 = "http://c.biancheng.net/java/";auto f1 = 2.5;decltype(n1*6.7) f2;

这些用法在前面的两节中已经进行了分析,此处就不再赘述了。

对 cv 限定符的处理

「cv 限定符」是 const 和 volatile 关键字的统称:

  • const 关键字用来表示数据是只读的,也就是不能被修改;

  • volatile 和 const 是相反的,它用来表示数据是可变的、易变的,目的是不让 CPU 将数据缓存到寄存器,而是从原始的内存中读取。

在推导变量类型时,auto 和 decltype 对 cv 限制符的处理是不一样的。decltype 会保留 cv 限定符,而 auto 有可能会去掉 cv 限定符。以下是 auto 关键字对 cv 限定符的推导规则:

  • 如果表达式的类型不是指针或者引用,auto 会把 cv 限定符直接抛弃,推导成 non-const 或者 non-volatile 类型。

  • 如果表达式的类型是指针或者引用,auto 将保留 cv 限定符。

下面的例子演示了对 const 限定符的推导:

//非指针非引用类型const int n1 = 0;auto n2 = 10;n2 = 99;  //赋值不报错decltype(n1) n3 = 20;n3 = 5;  //赋值报错//指针类型const int *p1 = &n1;auto p2 = p1;*p2 = 66;  //赋值报错decltype(p1) p3 = p1;*p3 = 19;  //赋值报错

在 C++ 中无法将一个变量的完整类型输出,我们通过对变量赋值来判断它是否被 const 修饰;如果被 const 修饰那么赋值失败,如果不被 const 修饰那么赋值成功。虽然这种方案不太直观,但也是能达到目的的。n2 赋值成功,说明不带 const,也就是 const 被 auto 抛弃了,这验证了 auto 的第一条推导规则。p2 赋值失败,说明是带 const 的,也就是 const 没有被 auto 抛弃,这验证了 auto 的第二条推导规则。n3 和 p3 都赋值失败,说明 decltype 不会去掉表达式的 const 属性。

对引用的处理

当表达式的类型为引用时,auto 和 decltype 的推导规则也不一样;decltype 会保留引用类型,而 auto 会抛弃引用类型,直接推导出它的原始类型。请看下面的例子:

#include using namespace std;int main() {    int n = 10;    int &r1 = n;    //auto推导    auto r2 = r1;    r2 = 20;    cout << n << ", " << r1 << ", " << r2 << endl;    //decltype推导    decltype(r1) r3 = n;    r3 = 99;    cout << n << ", " << r1 << ", " << r3 << endl;    return 0;}

运行结果:

10, 10, 2099, 99, 99从运行结果可以发现,给 r2 赋值并没有改变 n 的值,这说明 r2 没有指向 n,而是自立门户,单独拥有了一块内存,这就证明 r 不再是引用类型,它的引用类型被 auto 抛弃了。给 r3 赋值,n 的值也跟着改变了,这说明 r3 仍然指向 n,它的引用类型被 decltype 保留了。

总结

auto 虽然在书写格式上比 decltype 简单,但是它的推导规则复杂,有时候会改变表达式的原始类型;而 decltype 比较纯粹,它一般会坚持保留原始表达式的任何类型,让推导的结果更加原汁原味。从代码是否健壮的角度考虑,我推荐使用 decltype,它没有那么多是非;但是 decltype 总是显得比较麻烦,尤其是当表达式比较复杂时,例如:

vector nums;
decltype(nums.begin()) it = nums.begin();

而如果使用 auto 就会清爽很多:

vector nums;
auto it = nums.begin();

在实际开发中人们仍然喜欢使用 auto 关键字(我也这么干),因为它用起来简单直观,更符合人们的审美。如果你的表达式类型不复杂,我还是推荐使用 auto 关键字,优雅的代码总是叫人赏心悦目,沉浸其中。

stdmove 跟 左键引用 区别_C++ auto和decltype的区别相关推荐

  1. stdmove 跟 左键引用 区别_JavaScript 基本数据类型和引用类型的区别详解

    js基本数据类型: js基本数据类型包括:undefined,null,number,boolean,string.基本数据类型是按值访问的,就是说我们可以操作保存在变量中的实际的值 1. 基本数据类 ...

  2. auto和decltype的区别

    C++ auto和decltype关键字 C++11新标准引入了auto和declty这两个类型推断关键字,auto的推断是基本上针对赋值类型,而decltype则常常希望重表达式中推断出要定义变量的 ...

  3. c语言和java的区别_C语言和Java的区别有哪些

    C语言和Java的区别有哪些 作为编程界的两大编程语言-C语言和Java,它们之间有什么不同呢?下面小编给大家整理了C语言和Java的区别,供大家参阅. 1.C语言 C语言是一门通用计算机编程语言,应 ...

  4. c#和java的区别_C#和java的语法区别

    通过这几天,看java视频,总结了一下java与C#的部分语法区别. 1.基本类型 Java是由byte,short,int,long,float,dboule组成,所有类型都是有符号的. C#除了这 ...

  5. c和python区别_C语言和python的区别

    Python可以说是目前最火的语言之一了,人工智能的兴起让Python一夜之间变得家喻户晓,Python号称目前最最简单易学的语言,现在有不少高校开始将Python作为大一新生的入门语言.本萌新也刚开 ...

  6. c 与java的区别_C/C++与java的区别

    Java并不仅仅是C++语言的一个变种,它们在某些本质问题上有根本的不同:(1)Java比C++程序可靠性更高.有人曾估计每50行C++程序中至少有一个BUG.姑且不去讨论这个数字是否夸张, 但是任何 ...

  7. r语言和python的区别_c语言和python的区别

    c语言和python的区别 1.语言类型不同. Python是一种动态类型语言,又是强类型语言.它们确定一个变量的类型是在您第一次给它赋值的时候.C 是静态类型语言,一种在编译期间就确定数据类型的语言 ...

  8. 《C++ Primer 第五版》第二章(第5小节)——using和typedef,auto和decltype总结

    1.using和typedef(作用:定义类型别名) 1)typedef和using都可以用来定义一个类型别名,二者在类型别名上定义没有区别.只是需要注意的是类型和类型别名的顺序,使用typedef定 ...

  9. c 表达式必须是可修改的左值_C++中的左值,右值,左值引用,右值引用

    童帅 2020-2-22 文中的"表达式"都是指赋值表达式 左值,右值,左值引用,右值引用 到底是什么 左值和右值 int a = 10; int b = 5; int c = a ...

最新文章

  1. Nature子刊:精胺介导稻瘟病菌侵染水稻叶片的新机制!
  2. zabbix3.2.6.1升级3.4.4图文心得
  3. 歌手比赛系统c语言程序注释,C语言程序课程设计—歌手比赛系统(20页)-原创力文档...
  4. RabbitMQ声明队列参数作用详解
  5. 13 - java包装类
  6. mysql二进制日志特点_MySQL二进制日志分析-概述篇
  7. sudo: unable to resolve host iZ2zecsdy8flu603bmdg1bZ
  8. Confluence 6 通过 SSL 或 HTTPS 运行 - 创建或请求一个 SSL 证书
  9. win11u盘安装报错怎么办 windows11u盘安装报错的解决方法
  10. Ubuntu下yolov4训练自己的数据集
  11. Zigbee协议栈中文说明
  12. 利用rufus重装ubuntu
  13. 【备忘】Pr基本操作
  14. LabVIEW虚拟数字示波器
  15. 超详细图文教程·阿里云免费学生ECS云服务器领取并使用全过程(部署Python多人聊天室程序)
  16. 项目微商城的抽奖活动小结
  17. [高项]关键路径法VS关键链法
  18. 【Git版本控制】Git基础入门和分支管理
  19. 5.23 综合案例2.0-番茄时钟(2.2版本接口有更新)
  20. 【日语】【歌词】「ヤキモチ」--高橋優

热门文章

  1. [轉]解决Windows XP下缩略图显示模式下文件夹没有名称的方法
  2. oracle的sum函数精度问题_Excel中的这些烧脑问题,你遇到过几种?
  3. 火狐marquee_火狐不支持marquee解决方案
  4. 自动化比手工测试成本高?使用Selenium评估测试自动化的ROI指标
  5. 绝地求生更新完后显示服务器忙,绝地求生2月1日更新好了吗?更新后提示服务器繁忙怎么办?...
  6. mysql索引级别快慢_面试小点-MySQL 的两种索引方法如何提高查询速度
  7. python中属性与方法_python中属性和方法的动态绑定
  8. linux快速查找文件中所包含的指定字段的个数
  9. ubuntu下的常见12个命令---欢迎补充
  10. 公司新来了个00后测试卷王,老油条表示是真干不过,已被……