C++ 11 auto 与 decltype
Posted Overboom
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 11 auto 与 decltype相关的知识,希望对你有一定的参考价值。
C++11 引入了auto和decltype关键字实现类型推导,通过这两个关键字不仅能方便地获取复杂类型,而且还能简化书写,提高编码效率。
1. auto
编程时候常常需要把表达式的值付给变量,需要在声明变量的时候清楚的知道变量是什么类型。然而做到这一点并非那么容易(特别是模板中),有时候根本做不到。为了解决这个问题,C++11新标准就引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。和原来那些只对应某种特定的类型说明符(例如 int)不同。auto 让编译器通过初始值来进行类型推演。从而获得定义变量的类型,所以说 auto 定义的变量必须有初始值。
1.1 auto推导规则
auto可以同指针、引用结合起来使用,还可以带cv限定符(cv-qulifier, const和volatile限定符的统称)。
int x = 0;
auto *a = &x; // a为int*, auto被推导为int
auto b = &x; // b为int*, auto被推导为int *
auto &c = x; // c为int &, auto被推导为int
auto d = c; // d为int, auto被推导为int
const auto e = x; // e为const int
auto f = e; // f 为int
const auto &g = x; // g为const int&
auto& h = g; // f为const int &
通过上面示例,可以得到两条规则:
1> 当不声明指针或引用时,auto的推导结果和初始化表达式抛弃引用cv限定符后类型一致
2> 当声明为指针或引用时,auto的推导结果将保持初始化表达式的cv属性。
1.2 auto的限制
void func(auto a = 1) // error: auto不能用于函数参数
struct Foo
auto var_ = 0; //error:auto不能用于非静态成员变量
static const auto var2_ = 0; //OK: var2_ 为static const int
;
template <typename T>
struct Bar ;
int main(void)
int arr[10] = 0;
auto aa = arr; // ok,aa为int
auto rr[10] = arr; // error,auto无法定义数组
Bar<int> bar;
Bar<auto> bb = bar; // error:auto无法推导出模板参数
return 0;
1> auto不能用作函数参数
2> auto不能用于非静态成员变量
3> auto不能定义数组
1.3 用到auto的场景
1> STL容器遍历
#include <string>
#include <iostream>
#include <map>
using namespace std;
int main()
map<int, string>mp;
mp.insert(make_pair(1, "Tom"));
mp.insert(make_pair(2, "Mike"));
mp.insert(make_pair(3, "Jack"));
//for (std::iteraor it = mp.begin(); it != mp.end(); it++)
for (auto it = mp.begin(); it != mp.end(); it++)
cout << it->first << " " << it->second << endl;
return 0;
2> 范式编程
#include <iostream>
#include <string>
using namespace std;
class T1
public:
static int get()
return 10;
;
class T2
public:
static string get()
return "hello world";
;
template<typename T,typename P>//不用auto
void func01()
P ret = T::get();
cout << ret << endl;
template<typename T>//用auto
void func()
auto ret = T::get();
cout << ret << endl;
int main()
func<T1>();
func<T2>();
cout << "------------------------------" << endl;
func01<T1, int>();
func01<T2, string>();
return 0;
2. decltype
在某些情况下,不需要或者不能定义变量,但是希望得到某种类型,这时候就可以使用 C++11 提供的 decltype 关键字了,它的作用是在编译器编译的时候推导出一个表达式的类型,语法格式如下:
decltype(表达式)
decltype 是 “declare type” 的缩写,意思是 “声明类型”。decltype 的推导是在编译期完成的,它只是用于表达式类型的推导,并不会计算表达式的值。
decltype 推导的表达式可简单可复杂,在这一点上 auto 是做不到的,auto 只能推导已初始化的变量类型。
2.1 decltype推到规则
分三种场景讨论decltype的推导规则:
1> 表达式为 普通变量/普通变量表达式/类表达式,这种情况使用decltype推导出的类型和表达式的类型一致
#include <iostream>
#include <string>
using namespace std;
class Test
public:
string text;
static const int value = 110;
;
int main()
int x = 99;
const int &y = x;
decltype(x) a = x;
decltype(y) b = x;
decltype(Test::value) c = 0;
Test t;
decltype(t.text) d = "hello, world";
return 0;
解析如下:
变量 a 被推导为 int 类型
变量 b 被推导为 const int & 类型
变量 c 被推导为 const int 类型
变量 d 被推导为 string 类型
2> 表达式是函数调用,使用 decltype 推导出的类型和函数返回值一致。
class Test...;
//函数声明
int func_int(); // 返回值为 int
int& func_int_r(); // 返回值为 int&
int&& func_int_rr(); // 返回值为 int&&
const int func_cint(); // 返回值为 const int
const int& func_cint_r(); // 返回值为 const int&
const int&& func_cint_rr(); // 返回值为 const int&&
const Test func_ctest(); // 返回值为 const Test
//decltype类型推导
int n = 100;
decltype(func_int()) a = 0;
decltype(func_int_r()) b = n;
decltype(func_int_rr()) c = 0;
decltype(func_cint()) d = 0;
decltype(func_cint_r()) e = n;
decltype(func_cint_rr()) f = 0;
decltype(func_ctest()) g = Test();
解析如下:
变量 a 被推导为 int 类型
变量 b 被推导为 int& 类型
变量 c 被推导为 int&& 类型
变量 d 被推导为 int 类型
变量 e 被推导为 const int & 类型
变量 f 被推导为 const int && 类型
变量 g 被推导为 const Test 类型
函数 func_cint () 返回的是一个纯右值(在表达式执行结束后不再存在的数据,也就是临时性的数据),对于纯右值而言,只有类类型可以携带const、volatile限定符,除此之外需要忽略掉这两个限定符,因此推导出的变量 d 的类型为 int 而不是 const int。
3> 表达式是一个左值,或者被括号 ( ) 包围,使用 decltype 推导出的是表达式类型的引用(如果有 const、volatile 限定符不能忽略)。
#include <iostream>
#include <vector>
using namespace std;
class Test
public:
int num;
;
int main()
const Test obj;
//带有括号的表达式
decltype(obj.num) a = 0;
decltype((obj.num)) b = a;
//加法表达式
int n = 0, m = 0;
decltype(n + m) c = 0;
decltype(n = n + m) d = n;
return 0;
解析如下:
obj.num 为类的成员访问表达式,符合场景 1,因此 a 的类型为 int
obj.num 带有括号,符合场景 3,因此 b 的类型为 const int&。
n+m 得到一个右值,符合场景 1,因此 c 的类型为 int
n=n+m 得到一个左值 n,符合场景 3,因此 d 的类型为 int&
2.2 decltype的应用
关于 decltype 的应用多出现在泛型编程中。
3. decltype和auto的结合使用 — 返回类型后置语法
在泛型编程中,可能需要通过参数的运算来得到返回值的类型。
以上是关于C++ 11 auto 与 decltype的主要内容,如果未能解决你的问题,请参考以下文章
C++11新特性:3—— C++ decltype类型推导完全攻略