1. auto
在C++11之前,auto和static相对应用于表示变量是自动存储的,但是非static局部变量默认都是自动存储的,auto因此显得额外鸡肋。C++11中对auto进行了扩展,使他能够自动推导变量的实际类型。
1.1 推导规则
C++中auto并不是一种数据类型,而是一种用于声明类型的占位符
。在使用auto时,必须对变量进行初始化
,这样编译器才能推导出其实际数据类型,从而在编译时
将auto替换为真正的数据类型。
auto简单使用:
auto a = 1;
auto b = 3.14;
auto c = 'a';
// auto d; 这里会报错,因为d没有经过初始化,无法使用auto
与指针、引用结合:
当auto和指针、引用结合时,可以带上const、volatile关键字,其推导规则如下:
- 当变量是指针或引用类型时,推到结果才会带上const、volatile关键字。否则将会省略。
实例如下:
int temp = 1;
auto *a = &temp;
auto b = &temp;
auto &c = temp;
auto d = temp;
- a类型为
int *
,因此auto的推导结果为int
。 - b类型为
int *
,因此auto的推导结果为int *
。 - c类型为
int &
,因此auto的推导结果为int
。 - d类型为
int
,因此auto的推导结果为int
。
当带上const关键字时:
int tmp = 250;
const auto a = tmp;
auto b = a;
const auto &c = tmp;
auto &d = c;
- a类型为
const int
,因此auto的推导结果为int
。 - b类型为
int
,因为b并没有声明为指针或是引用类型,因此const关键字被删去,auto的推导结果为int
。 - c类型为
const int&
,因此auto的推导结果为int
。 - d类型为
const int&
,d被声明为引用类型,const关键字得以保留,因此auto的推导结果为int
。
1.2 auto限制
在一些场合中,auto关键字无法使用。
-
不能作为函数参数使用。因为只有在函数调用时才会给到函数实参(程序运行时),而auto要求必须为变量初始化(编译时)。
-
不能用于类的非静态成员初始化:
class Test{ private: // auto int a = 0; 编译报错。 // static auto int b = 0; 编译报错,类的静态非常量成员必须在类外进行初始化 const static auto int c = 0; // 编译通过 }
-
不能使用auto关键字定义数组。
-
不能使用auto推导模板参数:
template <typename T> class Test{} int main(void){ Test<int> t1; // Test<auto> t2 = t1; 错误,无法使用auto推导模板参数 return 0; }
1.3 auto的应用
用于stl容器的遍历
-
C++98中:
#include <map> #include <string> int main(void){ map<int,string> person; map<int,string>::iterator it = person.begin(); for(; it != person.end(); ++it){ ... } return 0; }
-
C++11中,使用auto:
#include <map> #include <string> int main(void){ map<int,string> person; for(auto it = person.begin(); it != person.end(); ++it){ ... } return 0; }
用于泛型编程:在使用模板时,有时并不知道变量应当定义什么类型,这时就可以使用auto:
#include <iostream>
#include <string>
using namespace std;
class A{
public:
static int show(){
return 1;
}
};
class B{
public:
static string show(){
return "aaa";
}
};
template <class T>
void func(){
auto result = T::show();
cout << result << endl;
}
int main(void){
func<A>();
return 0;
}
2. decltype
在某些情况下,我们希望通过表达式来获取某种类型,从而对变量进行定义,这时就可以使用decltype
(是declare type的缩写)。
Eg:
int a = 10;
decltype(a) b = 100;
decltype(a+1.1) c = 3.14;
- b被推导为int类型。
- c被推导为double类型。
decltype的优势在于它能够在编译时
推导复杂的表达式类型,而auto只能推导已初始化的变量类型。
2.1 推导规则
delctype的推导结果分情况而定:
-
表达式是普通变量/普通表达式/类表达式,推导出的类型和表达式的类型一致。
-
表达式是函数调用,使用decltypoe推导出的类型和函数返回值一致。
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
类型:因为func_cint()
返回了一个右值,而对于右值而言,只有类才能携带const、volatile类型
,因此需要忽略这两个限定符。 - 变量e被推导为
const int &
类型 - 变量f被推导为
const int &&
类型 - 变量g被推导为
const Test
类型。虽然func_ctest()
返回了一个右值,但因为这个右值是一个对象,因此可以携带const、volatile类型。
- 变量a被推导为
-
表达式不是一个变量并且是一个左值,或者表达式被
()
包围,那么使用decltype推导出来的是表达式类型的引用(如果有const、volatile不能忽略):class Test{ public: int a; }; int main(void){ int x = 10, y = 20; decltype(x) a = 10; decltype(x+y) b = 20; decltype(x = x + y) c = x; const Test t; decltype(t.a) d = 10; decltype((t.a)) e = x; return 0; }
- a:普通变量,推导出
int
类型。 - b:普通表达式,推导出
int
类型 - c:表达式,但最终返回左值,因此推导出
int &
类型。 - d:普通变量,推导出
int
类型。 - e:表达式被
()
包围,因此推导出cosnt int &
类型。
- a:普通变量,推导出
3. 返回类型后置
引入:
在泛型编程中,有时会遇到一种情况:返回值的类型由函数的参数决定。例如:
template <typename R, typename X, typename Y>
R add(X x, Y y){
return x + y;
}
上述代码可以,如果我们想通过decltype
进行优化:
template <typename X, typename Y>
decltype(x+y) add(X x, Y y){
return x + y;
}
这样会报错
,因为delctype
在编译阶段就要得出推导结果,但模板函数的参数类型却是在运行时才确定的,自然无法通过编译。为了解决这一问题,C++11引入了返回类型后置。
概述:
所谓返回后置类型,实际上就是将decltype
和auto
结合起来完成类型的推导。语法格式如下:
auto func(参数1, 参数2, ...) -> delctype(参数表达式)
通过上述语法,auto会自动追踪delctyple推导出的类型
。所以函数可以修改为:
template <typename X, typename Y>
auto add(X x, Y y) -> decltype(x+y){
return x + y;
}
标签:const,推导,int,auto,自动,类型,decltype
From: https://www.cnblogs.com/beasts777/p/17875397.html