C++是一种强类型的语言,比如变量a,如果声明它是整型,则之后只能将它作为整型来用。这和其他弱类型的语言有很大的区别,比如python中,我们可以让a在第一行是个整型,第三行是一个字符串。(转载请指明出于breaksoftware的csdn博客)

a = 3
print a
a = "3"
print a

C++代码在声明一个变量时就已经明确指定了它的类型。这样在编译器给它分配内存时,就知道分配出什么多大的空间。从这个角度来说,C++的语法是站在编译器实现的角度设计的。然而随着编程技术的普及,大家都希望代码写出来是给人看的,而不是给机器看的。但是在C++代码的一些场景下,有一定基础的程序员都可以通过右值推导出左值变量类型时,编译器还是要求写明类型,这无疑加重了程序员的负担。比如下面的代码

std::vector<int> vec_int;
……
std::vector<int>::iterator iter = vec_int.begin();

如果不看变量iter的类型声明,我们也可以通过vector的begin()函数返回值类型推导出变量的类型。这样的推导编译器也完全可以完成。但是在C++11之前的标准中,我们也只能这种笨拙的方式去声明。因为老的标准没要求编译器完成这样的工作,而且即使各大编译器厂商“超前”的完成了,也没有一种统一的途径可以表达出来。

于是在C++11的标准中引入了auto关键字,它让上述类型推导通过统一的标准表达出来。我们可以使用auto去声明一个变量,但是这并不意味着C++增加了一个auto类型——一个可以表示任意类型的类型。因为强类型特性是不会变的,变的只是编译器,它变的更加高级——推导出确定的类型。这儿特别需要指出的是:auto关键字并不是在预编译过程中被替换成确定类型的。大家可以开启VS2017的“生成预编译文件”选项来验证这点。

std::vector<int> vec_int;
……
auto iter = vec_int.begin();

上述代码中auto便将std::vector<int>::iterator替换了,这在一定程度上降低了程序员的负担。

在C++11标准推出之前,我们可以使用别名来减少负担。比如会在一个共有的头文件中做如下定义:

typedef std::vector<int> VecInt;
typedef VecInt::iterator VecIntIter;
typedef VecInt::const_iterator VecIntCIter;

然后在代码中使用上述别名

VecInt vec_int;
……
VecIntIter = vec_int.begin();

当然这不失为一种方法,但是这就要求每定义一个容器,都要别名它相应的迭代器。auto的出现帮我们省掉了这些繁琐且意义不大的书写。

auto是个非常好的设计,但是也不可毫无原则的滥用。

作为C++标准,要求auto变量在声明时要被初始化。该初始化操作其实就是指定了其真实类型。一般我们可以使用表达式来初始化一个变量,也可以使用字面值、字面量、常量或者一个明确类型的变量。不管我们使用哪种方式,都希望auto的推导不会产生“歧义”。比如

auto i = 0x01;

在VS2017中,我们将其类型打印出来(typeid(i).name())是int。那可能会问,为什么不是unsigned int,long等呢?现在我们换个字面值(8个f)

auto i = 0xffffffff;

此时,编译器就会认为类型为unsigned int。我们再修改字面值(15个f,1一个0)

auto i = 0x0fffffffffffffff;

编译器推导出的类型是__int64。我们再将类型改成(16个f)

auto i = 0xffffffffffffffff;

编译器推导出的类型是unsigned __int64。

可以见得,在使用字面值或者字面量初始化auto变量时往往会产生“误解”。所以一旦我们自己对推导产生疑问时,最好使用明确的类型来定义变量。

其次,不要寄希望于编译器可以通过构造函数隐式转换推导类型。比如下面的初始化方式,我们可能会认为变量类型是std::string。

auto i = "which type?";

但是真实的推导类型是char const *。为什么呢?因为当我们使用

std::string i = "which type?"; 

赋值符将会触发basic_string类构造函数隐式转换(《C++拾趣——类构造函数的隐式转换》)

 basic_string(_In_z_ const _Elem * const _Ptr): _Mybase(){   // construct from [_Ptr, <null>)_Tidy_init();assign(_Ptr);}

这是由于左值已经指定类型才会发生的。所以如果使用auto定义一个字面量,其类型是char const *。鉴于理解这样的过程需要掌握一定的C++基础知识,所以我也不建议在这个场景下使用auto去定义变量。

综上所述,除了在模板中必要的地方使用auto外,其他地方都需要可以从右值一眼看出类型,否则就会产生理解上的歧义或者困扰。

C++拾趣——C++11的语法糖auto相关推荐

  1. C++拾趣——有趣的操作符重载

    操作符重载是C++语言中一个非常有用的特性.它可以让我们比较优雅的简化代码,从而更加方便的编写逻辑. 为什么要使用操作符重载 一种常见的用法是重载<<运算符,让标准输出可以输出自定义的类型 ...

  2. C#语法糖(Csharp Syntactic sugar)大汇总

    首先需要声明的是"语法糖"这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换:而且可以提高开发编码的效率,在性能上也不会带来损失.这让java开发人员羡慕 ...

  3. 看看C# 6.0中那些语法糖都干了些什么(终结篇)

    终于写到终结篇了,整个人像在梦游一样,说完这一篇我得继续写我的js系列啦. 一:带索引的对象初始化器 还是按照江湖老规矩,先扒开看看到底是个什么玩意. 1 static void Main(strin ...

  4. Kotlin 中的 run、let、with、apply、also、takeIf、takeUnless 语法糖使用和原理分析

    这些Kotlin的语法糖函数经常用,但也很容易搞混,所以转载一下,若混了可以回来再看 转载自公众号:纸上浅谈 正文: 在 Kotlin 有一些可以简化代码的语法糖,比如 run.let.with.ap ...

  5. 几个 Python 语法糖的实现

    受这位小哥(https://github.com/czheo/syntax_sugar_python)的启发,我照着它的 Usage 实现了一部分语法糖. 1. compose 实现compose函数 ...

  6. 看看C# 6.0中那些语法糖都干了些什么(上篇)

    一:自己主动初始化属性 确实这个比之前的版本号简化了一下.只是你肯定非常好奇.究竟编译器给我们做了哪些东西呢? 1 class Student 2 { 3 public string Name { g ...

  7. Python中常见的语法糖

    Python中常见的语法糖 知识点导航: 1. 横线分隔符 2. 交换两个变量的值 3. 判断变量是否在范围内 4. 字符串的乘法 5. 列表相加 6. 列表切片 7. 解压序列赋值给多个变量 8. ...

  8. Java语法糖1:可变长度参数以及foreach循环原理

    语法糖 接下来几篇文章要开启一个Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的 ...

  9. 第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)

    一. 监视锁(Monitor和lock) 1. Monitor类,限定线程个数的一把锁(Synchronized lock是他的语法糖),两个核心方法: Enter:锁住某个资源. Exit:退出某一 ...

最新文章

  1. Java线程池实现原理及其在美团业务中的实践
  2. php调用webservice报错Class 'SoapClient' not found
  3. 你必须学会HTML和CSS的9大理由,让你在以后的工作中更香
  4. vue开发看这篇文章就够了 vue知识大全
  5. Android批量图片加载经典系列——使用LruCache、AsyncTask缓存并异步加载图片
  6. 对学习linux一周的总结
  7. paypal java_PaypalUtil PayPal付款JAVA工具类
  8. 计算机的好与坏作文,电脑“坏”了的作文
  9. android 手机网络可以连上,wifi连上后访问不了服务器,Nexus连接WiFi成功,但提示“已连接 但无法访问互联网”...
  10. 管理服务之间的依赖关系
  11. FPGA设计经验之图像处理
  12. 云盘里资料被和谐了,怎么办?
  13. 微型计算机原理与接口技术(周荷琴 冯焕清)第六版 课后习题答案 第一章(部分答案)
  14. distinct (去重)
  15. 12. STM32——硬件IIC驱动OLED屏幕显示
  16. java基础-接口与实现
  17. 什么是m3u8、f4v格式的文件
  18. Windows 软件推荐 - 小黄条 全平台同步桌面便签
  19. java取北京时间_JAVA 获取北京时间 亲自验证
  20. linux命令中 “|” 管道符号

热门文章

  1. 深蓝学院的深度学习理论与实践课程:第一章
  2. QueryPerformanceFrequency用法--Windows高精度定时计数
  3. OpenCV求逆(伪逆)矩阵函数
  4. 让你爽到飞起的【懒人插件AutoScssStruct4Vue】VSCode根据template的标签目录一键生成SCSS/LESS结构,敏捷开发必备插件!!!
  5. [综合面试] 计算机面试书籍与求职网站推荐
  6. 性能测试八:jmeter进阶之beanshell
  7. 关于python3与python2同时存在情况下导入pyqt失败解决记录
  8. c潭州课堂25班:Ph201805201 MySQL第二课 (课堂笔记)
  9. Git详解之九 Git内部原理
  10. centos7下安装docker(11容器操作总结)