在c++11中我们可以使用 auto自动推导变量的类型,还可以结合declttype来表示函数的返回值
一、auto关键字
(一)auto的推导规则
在c++11中auto并不代表一种实际的数据类型只是一个类型声明的"占位符"
- auto在使用时必须对auto声明的变量初始化,从而让编译器推导出他的示例类型,在编译时自动将auto替换为真正的数据类型
auto 变量名 = 变量值;
#include <iostream>
using namespace std;
void test(){
auto x=10;
auto y="hello world";
auto z=true;
cout<<typeid(x).name()<<endl;
cout<<typeid(y).name()<<endl;
cout<<typeid(z).name()<<endl;
int temp =20;
auto *a = &temp;
auto b=&temp;
cout<<typeid(a).name()<<endl;
cout<<typeid(b).name()<<endl;
}
int main() {
test();
system("pause");
return 0;
}
- auto可以和指针、引用结合起来使用 也可以带上 const 、volatile限定符
- 当变量不是指针或者引用类型时,推导的结果不会保留 const volatile关键字
- 当变量是指针或者引用类型时,推导的结果会保留 const volatile关键字
int tmp = 250;
const auto a1 = tmp; //const int*
auto a2 = a1;
const auto &a3 = tmp;//const int*
auto &a4 = a3; //const int*
/*变量a1的数据类型为 const int,因此auto关键字被推导为 int类型
变量a2的数据类型为 int,但是a2没有声明为指针或引用因此 const属性被去掉, auto被推导为 int
变量a3的数据类型为 const int&,a3被声明为引用因此 const属性被保留,auto关键字被推导为 int类型
变量a4的数据类型为 const int&,a4被声明为引用因此 const属性被保留,auto关键字被推导为 const int类型*/
(二)auto的限制
- 不能作为函数的参数使用。因为只有在函数调用的时候才会给函数参数传递参数,auto要求必须给修饰的变量赋值,因此二者矛盾。
- 不能用于类的非静态成员变量的初始化(类的非静态成员是不属于类的是属于实例化对象的)
- 不能使用auto关键字定于数组
- 无法使用auto推导出模板参数
(三)auto的应用
- 用于STL容器的遍历
#include <iostream>
using namespace std;
#include <vector>
void test01(){
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
for(auto it=v.begin();it!=v.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
int main() {
test01();
system("pause");
return 0;
}
- 用于泛型编程
#include <iostream>
using namespace std;
class A1{
public:
static int get(){
return 100;
}
};
class A2{
public:
static string get(){
return "我被调用了";
}
};
template<typename T>
void function( ){
auto val =T::get();
cout<<"val:"<<val<<endl;
}
int main() {
function<A1>();
function<A2>();
system("pause");
return 0;
}
二、decltype
在不需要或者不能定义变量,但是希望的到某种类型,这时候可以适应decltype关键字,它的作用是在编译器编译时推导出一个表达式的类型
语法:decltype (表达式)
(一)基础用法
表达式为普通变量或者普通表达式或者类表达式,在这种情况下,使用decltype推导出来的类型哥表达式的类型是一致的。
#include <iostream>
using namespace std;
class Test
{
public:
string text;
static const int value = 1110;
};
void func(){
int a = 100;
decltype(a) b=99;
decltype(a+1.2) c=101.2;
decltype(a+b*c) d=1993.52;
decltype(Test::value) e=666;
cout<<"a:"<<a<<endl;
cout<<"b:"<<b<<endl;
cout<<"c:"<<c<<endl;
cout<<"d:"<<d<<endl;
cout<<"e:"<<e<<endl;
}
int main(){
Test t;
decltype(t.text) s="hello 666666";
cout<<"s:"<<s<<endl;
func();
return 0;
}
(二)表达式是函数调用
表达式是函数调用,使用decltype推导出的类型和函数返回值一致
对于纯右值而言,只有类类型可以携带const、volatile限定符,除此之外需要忽略掉这两个限定符
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
int main()
{
//decltype类型推导
int n = 100;
// a:int
decltype(func_int()) a = 0;
// b:int& 左值引用
decltype(func_int_r()) b = n;
// c:int&& 右值引用
decltype(func_int_rr()) c = 0;
// d: int 纯右值 ==》返回一个纯字面量 忽略 const
decltype(func_cint()) d = 0;
// e: const int& 左值引用
decltype(func_cint_r()) e = n;
// f: const int&& 右值引用
decltype(func_cint_rr()) f = 0;
// g: const Test
decltype(func_ctest()) g = Test();
return 0;
}
(三)表达式是一个左值
表达式是一个左值,或者被()包围,使用decltype推导出的是表达式类型的引用(如果有 const,volatile 限定符不能忽略)
左值:可以取到地址,通常是变量
右值:取不到地址,通常是常量
#include <iostream>
using namespace std;
class Test
{
public:
int a = 9;
string text;
static const int value = 10;
};
int main()
{
const Test t;
//带有括号的表达式
decltype(t.a) a=0; //a的类型为int
decltype((t.a)) b =a; //b的类型为const int &
//加法表达式
int n =0,m=0;
decltype(n+m) c = 0; //c的类型为int
decltype(n=n+m) d = n; //d的类型为int &
cout<<"wangdefa"<<endl;
return 0;
}
(四)decltype在泛型编程中的使用举例
示例代码:
#include <iostream>
#include <list>
using namespace std;
template<typename T>
class Container
{
public:
void print(T& t)
{
for(m_it = t.begin(); m_it!= t.end(); ++m_it)
{
cout << *m_it << " ";
}
}
private:
decltype(T().begin()) m_it; //自动推导迭代器类型
};
int main()
{
list<int> ls{1,2,3,4,5,6,7,8,9};
Container<list<int>> c;
c.print(ls);
return 0;
}
(五)返回类型后置
参数类型后置方法:
// 符号 -> 后边跟随的是函数返回值的类型
auto func(参数1, 参数2, ...) -> decltype(参数表达式)
#include <iostream>
using namespace std;
template <typename T, typename U>
// 返回类型后置语法
auto add(T t, U u) -> decltype(t+u)
{
return t + u;
}
int main()
{
int x = 520;
double y = 13.14;
auto z = add<int, double>(x, y);
auto z = add(x, y); // 简化之后的写法
cout << "z: " << z << endl;
return 0;
}