c++11中引入了auto和decltype关键字实现类型推导,通过这两个关键字不仅能够方便的获取复杂的类型,而且还能简化书写,提高编码效率。 
    auto和decltype的类型推导都是编译器在编译的时候完成的,auto是通过定义auto变量时候给出的表达式的值推导出实际类型,并且在声明auto变量时必须马上初始化;decltype通过表达式的值推导出实际的类型,但是可以只声明变量,而不赋值。

auto类型推导

1. auto推导
    auto x = 5; //被编译器推导为int类型
auto pi = new auto(1); //编译器推导为int
const auto* v = &x, u = 5; //v为 const int*, u为 const int
static auto y = 0.1; //y为static const double
auto s; //出错! auto变量不能只声明不初始化
2. auto推导规则

(1)当不声明为指针或引用时,auto的推导结果和初始化表达式抛弃引用和cv限定符后的类型一致;(cv限定符: const volatile限定符) 
(2)当声明为指针或引用时,auto的推导结果将保留初始化表达式的cv限定符。

    int x = 0;
auto *a = &x; //a为 int*
auto b = &x; //b为 int*,auto可以自动识别指针类型
auto &c = x; //c为 int&
const auto e = x; //e为const int
auto f = e; //f为int (非指针或引用,则不保留cv限定符)
const auto& g = x; //g 为 const int&
auto& h = g; //h 为 const int&(指针或引用,保留cv限定符)
auto k = g;
3. auto的限制

(1)auto不能用于函数参数 
(2)auto不能用于非静态成员变量 
(3)auto无法定义数组 
(4)auto无法推导出模板参数

void func(auto a = 1){};   //错误。auto不能用于函数参数
struct Foo{
    auto var1 = 0;      //错误,auto不能用于非晶态成员变量
    static const auto var2 = 0;
} template<typename T>
struct Bar{}; int main(){
    int arr[10] = {0};
    auto aa = arr;  //aa被推导为int*
    auto rr[10] = arr;  //错误,auto无法定义数组
    Bar<int> bar;
    Bar<auto> bb = bar; //错误,auto无法推导出模板参数
}
4. auto的使用场景

(1)变量类型名比较长比较复杂

    //比如stl容器
std::map< double, double> result_map;
std::map< double, double>::iterator it = result_map.begin();
for(; it != result_map.end(); ++ it){};
//通过auto可以简化为
for (auto it = result_map.begin(); it != result_map.end(); ++it);
std::unordered_multimap< int, int> result_map;
std::pair< std::unordered_multimap< int, int>::iterator, std::unordered_multimap< int, int>::iterator> range = result_map.equal_range(key);
//通过auto简化为
auto range = result_map.equal_range(key);

(2)无法确定变量应该定义为什么类型

class Foo{
public:
static int get(void){
return 0;
}
};
class Bar{
public:
static const char* get(){
return "hello world";
}
}; template<typename A>
void func(void){
auto val = A::get();
cout << val << endl;
}
int main(){
func<Foo>();
func<Bar>();
}

decltype类型推导

1. decltype推导

decltype可以在编译时推导一个表达式的类型,语法格式如下: 
decltype(exp). decltype只是推导表达式的类型,并不会对表达式求值。

    int x = 0;
decltype(x) y = 3; //y被推导为int类型
decltype(x + y) z = 0; //z被推导为int
const int a = 1;
decltype(a) b = 2; //被推导为const int,尽管非指针或引用,仍然保持cv限定符
const int& i = 9;
decltype(i) h = x; //const int&
decltype(z)* p = &x; //p 为int*

decltype通过表达式得到的类型,可以保留住表达式的引用以及const限定符。对于一般的标记符表达式,decltype精确的推导出表达式定义本身的类型,不会像auto那样舍弃引用和cv限定符

2. decltype推导规则

(1) exp是标识符,类访问表达式,decltype(exp)和exp的类型一致 
(2) exp是函数调用,decltype(exp)和返回值的类型一致 
(3) 其他情况,若exp是一个左值,则decltype(exp)是exp类型的左值引用,否则为和exp类型一致。

(1) exp是标识符,类访问表达式,decltype(exp)和exp的类型一致
(2) exp是函数调用,decltype(exp)和返回值的类型一致
(3) 其他情况,若exp是一个左值,则decltype(exp)是exp类型的左值引用,否则为和exp类型一致。 ```
(1)标识符、类访问表达式,则 decltype(exp)和exp的类型一致
class Foo{
public:
static const int Number = 0;
int x;
};
int n = 0;
volatile const int& x = n;
decltype(n) a = n; //int
decltype(x) b = n; //volatile const int&
decltype(Foo::Number) c = 0; //const int(没有static) Foo foo;
decltype(foo.x) d = 0; //int类型 (2) 函数调用,decltype(f(xx)) 和 函数返回值类型一致
const Foo f(){
...
}
decltype(f()) c; //const Foo (3) 带括号的表达式和加法运算表达式
struct Foo{
int x;
};
const Foo foo = Foo();
decltype(foo.x) a = 0; //a 被推导为int, 根据推导规则1
decltype((foo.x))b = a; //b 被推导为const int&,
//因为根据foo.x 为一个左值,可知括号表达式也是一个左值。则按照推导规则3,返回左值的引用,foo为const Foo,则foo.x为一个const int类型的左值,则decltype的推导结果 为 const int& int n = 1, m = 2;
decltype(n + m) c = 0; //c被推导为int, n + m 为右值,则推导规则3,
decltype(n += m) d = c; //d被推导为int &, n += m 为左值,则推导规则3,为exp的引用
//注意此时 n 仍然为1,而不是3,因为 decltype只是推导exp的类型,而不对exp进行求值
3. decltype的实际应用

(1)泛型编程中自动推导类型

  1. decltype(ContainerT().begin()) it_; //获得某种类型容器的迭代器

(2)通过变量表达式抽取变量类型

    vector<int> v;
....
decltype(v)::value_type i = 0; //知道v是一个vector,但是不知道里面的数据类型,则可以使用 decltype(v)::value_type

返回类型后置语法,auto和decltype结合使用

int& foo(int& i);
float foo(float& f);
//有如上两个函数,同名,但是返回值和参数类型不同。若想要用模板来实现两个同名函数的调用。
template<typename T>
decltype(foo(val)) func(T&val){
return val;
} //这样写编译不过,因为c++的返回值是前置语法,在返回值定义的时候参数变量还不存在,因此无法使用前置的decltype(foo(val)) 【需要获得decltype(foo(val))的时候,val还不存在】 但可以通过auto和decltype的自动类型推导完成。
template<typename T>
auto func(T& val) -> decltype(foo(val)) //返回值类型后置
{
return foo(val);
}

c++11——auto,decltype类型推导的更多相关文章

  1. 第4课 decltype类型推导

    第4课 decltype类型推导 一.decltype类型推导 (一)语法: 1.语法:decltype(expr),其中的expr为变量(实体)或表达式 2.说明: ①decltype用于获取变量的 ...

  2. 第2课 auto类型推导(1)

    第2课 auto类型推导(1) 一.auto类型推导 (一)与模板类型推导映射关系 1.auto类型推导与模板类型推导可以建立一一映射关系,它们之间存在双向的算法变换.auto扮演模板中T的角色,而变 ...

  3. Effective Modern C++翻译(3)-条款2:明白auto类型推导

    条款2 明白auto类型推导 如果你已经读完了条款1中有关模板类型推导的内容,那么你几乎已经知道了所有关于auto类型推导的事情,因为除了一个古怪的例外,auto的类型推导规则和模板的类型推导规则是一 ...

  4. 类型推导:函数模板与auto

    1.从函数模板谈起 函数模板的类型推导机制是在c++98时代就有的,auto的类型推导机制与其基本一致,所以先理解函数模板类型推导. 函数模板可以用如下代码框架表示: #template<typ ...

  5. Effective Modern C++:01类型推导

    C++的官方钦定版本,都是以ISO标准被接受的年份命名,分别是C++98,C++03,C++11,C++14,C++17,C++20等.C++11及其后续版本统称为Modern C++. C++11之 ...

  6. 第1课 类型推导(1)_auto关键字

    1.  auto关键字 (1)auto的作用是让编译器自动推断变量的类型,而不需要显式指定类型.这种隐式类型的推导发生在编译期. (2)auto并不能代表实际的类型声明,只是一个类型声明的“占位符” ...

  7. C++11 类型推导decltype

    我们之前使用的typeid运算符来查询一个变量的类型,这种类型查询在运行时进行.RTTI机制为每一个类型产生一个type_info类型的数据,而typeid查询返回的变量相应type_info数据,通 ...

  8. C++11 类型推导auto

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

  9. C++11 - 类型推导auto关键字

    在C++11中,auto关键字被作为类型自动类型推导关键字 (1)基本用法 C++98:类型 变量名 = 初值;   int i = 10; C++11:auto 变量名 = 初值;  auto i ...

随机推荐

  1. SQL Server 禁止和启用约束

    Alter Table XXX nocheck constraint xxx Alter Table XXX check constraint xxx

  2. git commit 多行注释方法说明

    为了提高项目质量,不仅仅是代码的质量,而且还包括代码管理的质量. 所以,详细的git commit message 必不可少. 现在记录一下git commit 多行详细的commit 信息. 首先, ...

  3. ASP.NET中上传图片检测其是否为真实的图片 防范病毒上传至服务器

    一.需求 我们在用.net开发网站时,经常会用到图片上传,可以说是每个网站必备的,大到门户网站,电商网站,政务系统,OA系统,小到企业网站,个人网站,博客网站,导航网站等等,都有用到图片上传,那么在客 ...

  4. else好像必须做点什么,可以省点资源不做什么吗,else下不能用pass

    portfolio = [ {'name': 'IBM', 'shares': 100, 'price': 91.1}, {'name': 'AAPL', 'shares': 50, 'price': ...

  5. Html5 小球键盘移动

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...

  6. Python 随机数,break,continue

    #-*- coding:utf-8 -*- #导入模块 import random #打印10以内的随机数 num = 5 while num > 0: #random.randint(0,10 ...

  7. php插入htm htm插入php的变量

    <?php $file = "ueditor\php\upload\image\*\*.png"; foreach (glob("$file") as $ ...

  8. 关于Cocos2d-x中节点和精灵的关系以及初始化

    1.每一个对象类都有一个自己public的一个create函数(等价于CREATE_FUNC),和init函数. 2.create函数返回的是自身的类型,init函数是在ceate函数被调用的时候自动 ...

  9. ioc和aop的区别?

    ioc:控制反转(Inversion of Control,英文缩写为IoC)把创建对象的权利交给框架,是框架的重要特征,并非面向对象编程的专用术语.它包括依赖注入(Dependency Inject ...

  10. e661. 确定图像中是否有透明像素

    // This method returns true if the specified image has transparent pixels public static boolean hasA ...