C++11新特性:auto和decltype关键字

C++11新特性:auto和decltype关键字

  • 1、auto
    • 1.1 简介
    • 1.2 使用情况
    • 1.3 使用细则
      • 1.3.1 auto与指针和引用结合起来使用
      • 1.3.2 在同一行定义多个变量
    • 1.4 auto不能推导的场景
  • 2、decltype
  • 3、auto和decltype联合使用

1、auto

1.1 简介

  • 在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量;
  • C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器进行类型推导,auto声明的变量必须由编译器在编译时期推导而得。

1.2 使用情况

为什么使用auto:有些情况下可能不知道需要实际类型怎么设定,或者类型写起来特别复杂,使用auto

#include 
#include 
int main()
{
    short a = 32670;
    short b = 32670;
	// c如果给成short,会造成数据丢失,如果能够让编译器根据a+b的结果推导c的实际类型,就不会存在问题
	short c = a + b;
	
	std::map<std::string, std::string> m{{"apple", "苹果"}, {"banana","香蕉"}};
	// 使用迭代器遍历容器, 迭代器类型太繁琐
	std::map<std::string, std::string>::iterator it = m.begin(); 
	while(it != m.end())
	{
        cout<<it->first<<" "<<it->second<<endl;
		++it; 
	}
	return 0; 
}   

auto的使用

int TestAuto()
{
	return 10; 
}

int main() {
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = TestAuto();
	
	short aa = 32670;
    short bb = 32670;
	auto cc = aa + bb; //自动推导
	
	cout << typeid(b).name() << endl;//int
	cout << typeid(c).name() << endl;//char
	cout << typeid(d).name() << endl;//int
	//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
	return 0; 
}

1.3 使用细则

1.3.1 auto与指针和引用结合起来使用

  • auto声明指针类型时,用autoauto*没有任何区别
  • auto声明引用类型时则必须加**&**
int main() {
     int x = 10;
     auto a = &x;
     auto* b = &x; //和auto b=&x; 一样
     auto& c = x;  //定义引用
     
     cout << typeid(a).name() << endl;//int *
     cout << typeid(b).name() << endl;//int *
     cout << typeid(c).name() << endl;//int
     
     *a = 20;//x == *a == *b == c == 20
     *b = 30;//x == *a == *b == c == 30
     c = 40; //x == *a == *b == c == 40
     
     return 0;
}

1.3.2 在同一行定义多个变量

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错 。因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

void TestAuto()
{
     auto a = 1, b = 2; 
     auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同  对于编译器有二义性,没法推导
}

1.4 auto不能推导的场景

  1. auto 不能作为函数参数
// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导 
void TestAuto(auto var=1){}
  1. auto 不能定义类或者结构体的非静态成员变量
  void TestAuto(){
  	auto var=10//无法通过编译
  }
  1. auto不能直接用来声明数组
   void TestAuto(){
    int arr[] = {1,1,1};
	//auto b[] = { 2,2,2};//auto不能直接用来声明数组
}
  1. 实例化模板时不能使用auto作为模板参数
   vector<auto> x={1};// 无法通过编译

2、decltype

auto用于推导变量类型,而decltype则用于推导表达式类型,只用于编译器分析表达式的类型,表达式实际不会进行运算
decltype(e)推导并返回操作数对象e的数据类型,但不实际进行调用或运算
decltype会保留表达式的引用。

const int &i = 1;
int a = 2;
decltype(i) b = 2; //b是const int&

1.推演表达式类型作为变量的定义类型

#include 
using namespace std;

int main() {
	short a = 32670;
	short b = 32670;

	// 用decltype推演a+b的实际类型,作为定义c的类型 
	decltype(a + b) c;
	cout << typeid(c).name() << endl;	// int
	return 0;
}

  1. 推演函数返回值的类型
void* GetMemory(size_t size)
{
    return malloc(size);
}

int main() {
	// 如果没有带参数,推导函数的类型
	cout << typeid(decltype(GetMemory)).name() << endl;	// void * __cdecl(unsigned int)

	// 如果带参数列表,推导的是函数返回值的类型,注意:此处只是推演,不会执行函数 
	cout << typeid(decltype(GetMemory(0))).name() <<endl;	// void *
	return 0; 
}

3、auto和decltype联合使用

追踪返回类型
返回类型后置:在函数名和参数列表后面指定返回类型

template<typename T1,typename T2>
auto sum(const T1& t1,const T2 &t2)->decltype(t1+t2){
	return t1+t2;
}

错误案例

//情况1
template<typename T1,typename T2>
return_value sum(const T1& t1,const T2 &t2){// t1和t2类型不确定,无法推导出return_value类型
    return t1 + t2;
}
//情况2
template<typename T1,typename T2>
decltype(t1 + t2) sum(const T1& t1,const T2 &t2){// t1和t2类型不确定,在decltype(t1 +t2)推导时,t1和t2尚未定义,就会编译出错
    return t1 + t2;
}

返回值后置类型语法就是为了解决函数返回制类型依赖于参数但却难以确定返回值类型的问题。

你可能感兴趣的:(C++11新特性,c++,开发语言)