概述
在介绍类型推导之前,首先介绍下typeid,c++的运行时类型识别(RTTI)机制是为每个类型产生type_info类型的数据,typeid就会返回变量相应的type_info数据。type_info的name成员函数可以返回类型的名字,hash_code成员函数返回该类型唯一的哈希值,以供程序员对变量的类型随时进行比较。
class A {};
class B {};
struct C {};
int main()
{
int i;
A a1;
A a2;
B b;
C c;
cout << typeid(i).name() << endl;
cout << typeid(a1).name() << endl;
cout << typeid(a1).hash_code() << endl;
cout << typeid(a2).hash_code() << endl;
cout << typeid(b).hash_code() << endl;
return 0;
}
输出结果:
int
class A
1201377968
1201377968
2199077265
可见a1和a2的类型的哈希值一致,因为他们都是class A的对象。
auto,decltype类型推导
c++11将类型推导标准化为auto以及decltype,auto是从变量声明的初始化表达式获得变量类型,与auto不同的是decltype总是以一个普通表达式为参数,返回该表达式的类型。例如:
double foo()
{
return 1.0;
}
int main()
{
auto x = 1;
cout << typeid(x).name() << endl; // int
auto y = foo();
cout << typeid(y).name() << endl; // double
std::vector<int> vecList;
auto iter = vecList.begin();
cout << typeid(iter ).name() << endl; // std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types<int> > >
struct MyStruct
{
int i = 0;
};
struct MyStruct str;
auto str1 = str;
cout << typeid(str1).name() << endl; // struct `int __cdecl main(void)'::`2'::MyStruct
// auto z; 编译器报错,无法推导,声明时必须初始化
// z = x;
int i;
decltype(i) j = 0;
cout << typeid(j).name() << endl; // int
float a;
double b;
decltype(a + b) c;
cout << typeid(c).name() << endl; // double
typedef decltype(vecList.begin()) vectype;
vectype type;
cout << typeid(type).name() << endl;
return 0;
}
输出结果:
int
double
class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types > >
struct int __cdecl main(void)'::
2’::MyStruct
int
double
class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types > >
在代码清单中,可以看到,
auto“声明” z,但不立即对其进行定义,此时编译器会报错。auto声明必须被初始化,以使编译器能够从初始化表达式中推导出其类型。
decltype是返回其表达式的类型。
auto使用细则:
1、将变量x的指针赋给auto声明的变量,使用auto或auto*并没有什么区别,但是将变量x的引用赋给auto声明的变量,必须声明为auto&。例如:
int main()
{
int x;
auto a = &x;
auto *b = &x; // a == b
cout << "a:" << a << " b:" << b << endl;
auto c = x;
auto& d = x; // &c != &d
cout << "&c:" << &c << " &d:" << &d << endl;
}
输出结果:
a:00AFF7CC b:00AFF7CC
&c:00AFF7CC &d:00AFF79C
2、将一个被const或volatile(简称cv限定符)修饰的变量赋给auto声明的变量,auto声明的变量不会带走cv修饰,而引用可以。例如:
const int x = 1;
auto a = x;
auto& b = x;
a = 2;
b = 2; // 编译报错,因为b被const修饰,不能修改
3、在同一个赋值语句中,auto声明多个变量的类型,这些变量的类型必须相同,否则编译报错。例如:
int x;
int y;
float z;
auto a = x,b=y;
auto c = x,d = y,e = z; // 编译器报错,e与c,d类型不同
4、auto不能推导的情况:
a. auto不能声明函数的形参,如: int fun(auto x)会编译报错;
b. 对于结构体来说,非静态成员的类型不能为auto,即使设置了初始值也不行,编译器阻止了auto对结构体非静态成员的推导。 例如:struct str{ auto var = 10;};会编译报错。
c. 声明auto数组 .例如 auto a[3]; 编译器会报错
d. 实例化模板的时候使用auto作为模板参数。例如vector v; 会报错。
decltype推导四规则:
1、如果e是一个没有带()的表达式,或者类成员访问表达式,那么decltype(e)就是e所命名的实体类型,此外,如果e是一个被重载的函数,则会导致编译时错误。
2、否则,假设e的类型是T,如果e是一个将亡值,那么decltype(e)为T&&。
3、否则,假设e的类型是T,如果e是一个左值,则decltype(e)为T&。
4、否则,假设e的类型是T,则decltype(e)为T。
例如:
int i= 4;
int arr[5] = {0};
int *ptr = arr;
struct S {double d;} s;
void Overloaded(int);
void Overloaded(char);
int && RvalRef();
const bool Func(int);
// 规则一
decltype(arr) var1; // int[5]
decltype(ptr) var2; // int*
decltype(s.d) var3; // double
//decltype(Overloaded) var5 // 编译失败,是个重载函数
// 规则二
decltype(RevalRef()) var6 = 1; // int&&
// 规则三
decltype(true?i:i) var7 = i; // int&,三元运算符,返回一个i的左值
decltype((i)) var8 = i; // int&,带圆括号的左值
decltype(++i) var9 = i; // int&,++i返回i左值
decltype(arr[3]) var10 = i; // int&,[]操作返回左值
decltype(*ptr) var11 = i; // int&,*操作返回左值
decltype("lvar") var12 = "lvar"; // const char&[9],字符串常量为左值
//规则四
decltype(1) var13; // int,除字符串外为右值
decltype(i++) var14; // int,i++返回右值
decltype(Func(1)) var15; // const bool,圆括号可以忽略。
另外,与auto不同,decltype是能够带走cv限制符的,不过,如果对象的定义中有const或volatile限制符,使用decltype推导时,其成员不会继承const或volatile。例如:
const int a = 0;
volatile int b;
struct S{int i;};
const S d;
cout << is_const<decltype(a)>::value <<endl;// 1
cout << is_volatile<decltype(b)>::value <<endl; // 1
cout << is_const<decltype(d.i)>::value <<endl; // 0,成员不是const
is_const和is_volatile是检查类型是否是常量还是易失的。
追踪返回类型
语法:
template<typename T1,typename T2>
auto sum(T1& t1, T2& t2) -> decltype(t1+t2)
{
return t1 + t2;
}
复合符号-> decltype(t1+t2)被称为追踪返回类型。
最后
以上就是单身春天为你收集整理的c++11/14新特性解读之五 (auto,decltype 类型推导)的全部内容,希望文章能够帮你解决c++11/14新特性解读之五 (auto,decltype 类型推导)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复