C++auto/decltype关键字

outo简介

在早期C/C++中auto的含义是:使用auto 修饰的变量,是具有自动存储器的局部变量,但即使不加这个关键词,默认就是具有自动存储器的局部变量,所以说这个词几乎没有任何卵用。

C++11 中,标准委员会赋予了 auto 全新的含义即: auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

int TestAuto()
{
return 10;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = TestAuto();
//typeid(b).name()用于显示对用变量的类型,此函数返回一个字符串
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
return 0;
}

image-20220514143807735

【注意】

使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

使用细则

  1. auto的指针和引用:
    用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

    int main()
    {
    	int x = 10;
    	auto a = &x;
    	auto* b = &x;
    	auto& c = x;
    	cout << typeid(a).name() << endl;
    	cout << typeid(b).name() << endl;
    	cout << typeid(c).name() << endl;
    	*a = 20;
    	*b = 30;
    	c = 40;
    	return 0;
    }
    
    
  2. 在同一行定义多个变量
    当在同一行定义多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为auto其实就是占位,之后会根据后面的类型推导一个出来,但是如果后面放了两种不同类型变量,必崩好吧。

    void TestAuto()
    {
    	auto a = 1, b = 2;
    	auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同
    }	
    

outo不能推导的场景

  1. auto不能作为函数的参数或返回值

    auto TestAuto(auto a)
    {
    	return 3}
    

    此处的代码编译失败,因为编译器无法对 a 的实际类型进行推导;
    即使说这里的3作为是返回值可以被推导为int,但是当初在规定auto语法的时候就杜绝了让它做参数或返回值,防止了用户对 auto 的滥用,试想如果一个函数都是 auto 你还能直观判断到底传什么参数,用什么接受返回值吗?

  2. auto不能直接用来声明数组

    void TestAuto()
    {
    	int a[] = { 1,2,3 };
    	auto b[] = { 456 };
    }
    
  3. 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法

实际应用中的outo

  1. 自动推导较长类型

    看如下场景:

    #include <iostream>
    #include <map>
    #include <string>
    using namespace std;
    int main()
    {
        std::map<std::string, std::string> dict;
    	dict["sort"] = "排序";
    	dict["string"] = "字符串";
        std::map<std::string, std::string>::iterator it = dict.begin();//it前面都是它的类型
    }
    
    

    看不看的的懂不重要,知道std::map<std::string, std::string>::iterator是个变量名就行,而且他很长,

    这时候就可以用auto替换:

    std::map < std::string, std::string >::iterator it = dict.begin()
    auto it = dict.begin();
  2. 结合范围for使用:

    点我

decltype

auto是根据右侧的返回值进行推导

关键字decltype与其相似,将变量的类型声明为括号内表达式指定的类型。

与typeid的使用方法相同,但typeid是获取类型的字符串,而decltype获取后,自己就是那个类型

如:decltype(1+1) num;完全等同于int num;

// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
	decltype(t1 * t2) ret;
	cout << typeid(ret).name() << endl;
}
int main()
{
	const int x = 1;
	double y = 2.2;
	decltype(x * y) ret; // ret的类型是double
	decltype(&x) p; // p的类型是int*
	cout << typeid(ret).name() << endl;
	cout << typeid(p).name() << endl;
	F(1, 'a');
	return 0;
}
image-20220921001714870

上面的案例有些一般不会在实际应用中出现

declytype的一般用于推导lambda表达式的类型后用于模板参数

例如,priority_queue、map、unordered_map这些类模板可以通过向模板参数中传入一些仿函数用于比较,或者作为哈希函数,此时,我们就可以定义一个lambda表达式定义比较方法,模板参数需要传入一个类型,而不是lambda这种变量,此时就可以用declype推到出lambda的类型后传入。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值