自动类型推断

当编译器能够在一个变量的声明时候就推断出它的类型,那么你就能够用auto关键字来作为他们的类型:

  1. auto x = 1;

编译器当然知道x是integer类型的。所以你就不用int了。接触过泛型编程或者API编程的人大概可以猜出自动类型推断是做什么用的了:帮你省去大量冗长的类型声明语句。

比如下面这个例子:

在原来的C++中,你要想使用vector的迭代器得这么写:

  1. vector<int> vec;
  2. vector<int>::iterator itr = vec.iterator();

看起来就很不爽。现在你可以这么写了:

  1. vector<int> vec;
  2. auto itr = vec.iterator();

果断简洁多了吧。假如说自动类型推断只有这样的用法的话那未免也太naive了。在很多情况下它还能提供更深层次的便利。

比如说有这样的代码:

  1. template <typename BuiltType, typename Builder>
  2. void
  3. makeAndProcessObject (const Builder& builder)
  4. {
  5. BuiltType val = builder.makeObject();
  6. // do stuff with val
  7. }

这个函数的功能是要使用builder的makeObject产生的实例来进行某些操作。但是现在引入了泛型编程。builder的类型不同,那么makeObject返回的类型也不同,那么我们这里就得引入两个泛型。看起来很复杂是吧,所以这里就可以使用自动类型推断来简化操作:

  1. template <typename Builder>
  2. void
  3. makeAndProcessObject (const Builder& builder)
  4. {
  5. auto val = builder.makeObject();
  6. // do stuff with val
  7. }

因为在得之builder的类型之后,编译器就已经能知道makeObject的返回值类型了。所以我们能够让编译器自动去推断val的类型。这样一来就省去了一个泛型。

你以为自动类型推断只有这样的用法?那也太naive了。C++11还允许对函数的返回值进行类型推断

新的返回值语法和类型获取(Decltype)语句

 
在原来,我们声明一个函数都是这样的:
  1. int temp(int a, double b);

前面那个int是函数的返回值类型,temp是函数名,int a, double b是参数列表。

现在你可以将函数返回值类型移到到参数列表之后来定义:

  1. auto temp(int a, double b) -> int;

后置返回值类型可以有很多用处。比如有下列的类定义:

  1. class Person
  2. {
  3. public:
  4. enum PersonType { ADULT, CHILD, SENIOR };
  5. void setPersonType (PersonType person_type);
  6. PersonType getPersonType ();
  7. private:
  8. PersonType _person_type;
  9. };

那么在定义getPersonType函数的时候我们得这么写:

  1. Person::PersonType Person::getPersonType ()
  2. {
  3. return _person_type;
  4. }

因为函数所在的类Person是声明在函数返回值之后的,所以在写返回值的时候编译器并不知道这个函数是在哪个类里面。由于PersonTYpe是Person类的内部声明的枚举,所以在看到PersonType的时候,编译器是找不到这个类型的。所以你就得在PersonTYpe前面加上Person::,告诉编译器这个类型是属于Person的。这看起来有点麻烦是吧。当你使用新的返回值语法的时候呢就可以这么写:

  1. auto Person::getPersonType () -> PersonType
  2. {
  3. return _person_type;
  4. }

因为这次编译器看到返回值类型PersonType的时候已经知道这个函数属于类Person。所以它会到Person类中去找到这个枚举类型。

当然上述应用只能说是一个奇技淫巧而已。并没有帮我们多大的忙(代码甚至都没有变短)。所以还得引入C++11的另一个功能。

类型获取(Decltype)

 
既然编译器能够推断一个变量的类型,那么我们在代码中就应该能显示地获得一个变量的类型信息。所以C++介绍了另一个功能:decltype。(实在是不知道这个词该怎么翻译,姑且称之为类型获取)。
 
  1. int x = 3;
  2. decltype(x) y = x; // same thing as auto y = x;

上述代码就使用了类型获取功能。和函数返回值后置语法结合起来,可以有如下应用:

  1. template <typename Builder>
  2. auto
  3. makeAndProcessObject (const Builder& builder) -> decltype( builder.makeObject() )
  4. {
  5. auto val = builder.makeObject();
  6. // do stuff with val
  7. return val;
  8. }

前面的例子中这个函数的返回值是void,所以不需要为返回值引入泛型。如果返回值是makeObject的返回值的话,那么这个函数就得引入两个泛型。现在又了类型获取功能,我们就能在返回值中自动推断makeObject的类型了。所以decltype确实为我们提供了很大的便利。

 
这个功能非常重要,在很多时候,尤其是引入了泛型编程的时候,你可能记不住一个变量的类型或者类型太过复杂以至于写不出来。你就要灵活使用decltype来获取这个变量的类型。

c++11 类型推断的更多相关文章

  1. C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)

    #include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...

  2. C++11新特性:自动类型推断和类型获取

    声明:本文是在Alex Allain的文章http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-functi ...

  3. java 11 局部变量类型推断

    什么是局部变量类型推断? var javastack = "javastack"; System.out.println(javastack); 大家看出来了,局部变量类型推断就是 ...

  4. 现代C++之理解模板类型推断(template type deduction)

    理解模板类型推断(template type deduction) 我们往往不能理解一个复杂的系统是如何运作的,但是却知道这个系统能够做什么.C++的模板类型推断便是如此,把参数传递到模板函数往往能让 ...

  5. 现代C++之理解auto类型推断

    理解auto类型推断 上一篇帖子中讲述了模板类型推断,我们知道auto的实现原理是基于模板类型推断的,回顾一下模板类型推断: template <typename T> void f(Pa ...

  6. C++11 类型推导auto

    在C++11之前,auto关键字用来指定存储期.在新标准中,它的功能变为类型推断.auto现在成了一个类型的占位符,通知编译器去根据初始化代码推断所声明变量的真实类型.使用auto会拖慢c++效率吗? ...

  7. 译:Java局部变量类型推断(Var类型)的26条细则

    原文链接:https://dzone.com/articles/var-work-in-progress 作者:Anghel Leonard 译者:沈歌 Java局部变量类型推断(LVTI),简称va ...

  8. JDK11 | 第三篇 : 局部变量类型推断

    文章首发于公众号<程序员果果> 地址 : https://mp.weixin.qq.com/s/PB0Mw4bzjDML7nto2M8x2w 一.简介 Java局部变量类型推断(LVTI) ...

  9. TypeScript Type Innference(类型推断)

    在这一节,我们将介绍TypeScript中的类型推断.我们将会讨论类型推断需要在何处用到以及如何推断. 基础 在TypeScript中,在几个没有明确指定类型注释的地方将会使用类型推断来提供类型信息. ...

随机推荐

  1. HDU 3667 Transportation(网络流之费用流)

    题目地址:HDU 3667 这题的建图真是巧妙...为了保证流量正好达到k.须要让每一次增广到的流量都是1,这就须要把每一条边的流量都是1才行.可是每条边的流量并非1,该怎么办呢.这个时候能够拆边,反 ...

  2. hook NtReadVirtualMemory干扰杀软扫描

      信息来源:邪恶八进制信息安全团队(www.eviloctal.com)文章作者:asm(http://www.sbasm.cn) 写了个对抗扫描的东西,跟大家分享!技术含量不高,大牛飘过.一直以来 ...

  3. MySQL主从配置的一些总结

    有很多朋友做了mysql主从也有一段时间了,但是有时候也走了不少弯路,时间也浪费了不少,主要问题是没有查阅其他的主机配置的相关资料,而仅仅是看了配置文档,下面是作者对主从配置的一些总结. AD: 20 ...

  4. 以源码编译的方式安装PHP与php-fpm

    首先是最基本的下载,解压,编译安装(以PHP 5.3.6 为例): wget http://www.php.net/get/php-5.3.6.tar.gz/from/this/mirrortar x ...

  5. (void)0和0的区别及用法

    (void)0相当于宏NULL,NULL本身的含义为“空”,在c语言代表“不存在.不确定”的含义. 0不能简单的理解为“没有”的意思,在c语言及二进制中,0和1代表的是“一件事物的正反两个方面“,0是 ...

  6. 客户端在向服务器的动态页发出请求的时候,服务器才会创建session

    注意,纯的HTML页面很有可能导致服务器不会为用户创建session,即便是新到的用户也是如此. 在某些情况下也可能与服务器的具体配置有关系. 尤其是在对session进行监听的时候要注意这一点.

  7. Bootstrap学习笔记(6)--导航居中

    说明:没找到好办法 <div class="row"> <ul class="nav nav-pills col-md-offset-4"&g ...

  8. OpenERP 7 picking order 继承需要注意的地方

    stock.picking.out  和 stock.picking.in 都是继承自stock.picking 新添加columns时需要注意,在stock.picking.out和stock.pi ...

  9. at91 uart driver for vxworks

    /* at91UART.c - AT91RM9200 serial driver */ /* Copyright 2003-2004 Coordinate Co., Ltd. */ /* Copyri ...

  10. oozie4.3.0+sqoop1.4.6实现mysql到hive的增量抽取

    1.准备数据源 mysql中表bigdata,数据如下: 2. 准备目标表 目标表存放hive中数据库dw_stg表bigdata 保存路径为 hdfs://localhost:9000/user/h ...