【C/C++】【C++11】auto详解

auto类型常规推断

C++11中,auto用于自动类型推断,在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型,不需要程序员显示指定类型;

  • auto自动类型推断发生在编译器期间,所以不会影响程序执行期间的性能;
  • auto定义变量必须立即初始化;这样编译器才能推断它的实际类型;编译的时候才能确定auto的类型和整个变量的类型;编译期间可以用真正 的类型来替换auto
  • auto的使用灵活,可以和指针,引用,const等限定符结合使用;
  • auto推导出来以后代表一个具体类型;auto实际也是一个类型;
  • auto类型推断和函数模板推断类似;
  • auto也是类型声明的一部分;[可以理解成类型占位符]

传值方式

  • 传值方式的auto会抛弃引用,const等限定符;
auto x = 27;
const auto& xy = x; //xy = const int &
auto xy2 = xy; //xy2 = int,auto = int; 传值方式:引用类型会被抛弃,const属性会被抛弃,对方看成新副本;

using boost::typeindex::type_id_with_cvr;
cout << type_id_with_cvr<decltype(xy2)>().pretty_name() << endl;

传指针或引用但不是万能引用

指针或引用类型但不是万能引用,不会抛弃const等限定符,但是会丢弃引用;


#include <iostream>
#include <boost/type_index.hpp>


using namespace std;

//const auto &xy = x;
template <typename T> //T是类型模板参数,T是由类型的
void func(const T& tmp)//tmp形参,形参是有类型的 tmp形参的类型和T模板参数的类型不一样
{
	//T的类型不仅仅和调用者提供的实参有关系,还和tmp的类型有关;

	cout << "--------------s-----------------" << endl;
	using boost::typeindex::type_id_with_cvr;
	cout << "T = " << type_id_with_cvr<T>().pretty_name() << endl; //显示T类型
	cout << "tmp = " << type_id_with_cvr<decltype(tmp)>().pretty_name() << endl; //显示tmp类型
	cout << "---------------e----------------" << endl;
}

int main()
{  
	//auto类型推断和函数模板类型推断非常相似
	auto x = 27;
	const auto& xy = x; //xy = const int &

	auto xy2 = xy; //传值方式:引用类型和const类型都会被丢弃
	auto& xy3 = xy; //xy3 = const int &, auto = const int引用会被丢弃,cosnt属性保留

	auto y = new auto(100); // y = int*, auto = int*; auto可以用new操作符
	const auto* x_p = &x; //xp = const int *, auto  = int;


	auto* xp2 = &x; //xp2 = int *, auto = int;
	auto xp3 = &x; //xp3 = int *, auto = int *; xp3没有声明为指针,但auto把它推导成了指针类型


	//指针或引用类型但不是万能引用,不会抛弃const等限定符,但是会丢弃引用;
	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(xp3)>().pretty_name() << endl; //xy
	return 0; 
}

万能引用类型

#include <iostream>
#include <boost/type_index.hpp>


using namespace std;

int main()
{  
	//auto类型推断和函数模板类型推断非常相似

	//万能引用
	auto x = 27;
	const int x2 = x;
	auto&& yy = x; //x是左值,auto = int&, yy = int &, 出现了引用折叠,系统帮助我们处理掉了
	auto&& a_x2 = x2; //x2是左值,auto = int &, a_x2 = const int &
	auto&& a_x3 = 100; //100是右值,auto = int, a_x3 = int &&



	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(a_x2)>().pretty_name() << endl; //xy
	return 0; 
}

auto类型针对数组和函数的推断


#include <iostream>
#include <boost/type_index.hpp>
using namespace std;
void func(double x, int y) 
{
	cout << x << " " << y << endl;
};

int main()
{  
	const char str[] = "Hello world";
	auto arr = str; //const char *

	auto& my_arr2 = str; //const char (&)[12]

	int a[2] = { 1, 2 };
	auto a_au = a; //auto  = int *, a_au = int *

	auto tmp_f = func; // tmp_f = void(*) (double, int) 函数指针

	auto& tmp_f_ref = func; // tmp_f = void(&) (double, int) 函数引用

	tmp_f(1, 2);
	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(tmp_f_ref)>().pretty_name() << endl; //xy
	return 0; 
}

auto类型std::initializer_list的特殊推断


#include <iostream>
#include <boost/type_index.hpp>


using namespace std;


int main()
{  
	int x1 = 10; // c++98
	int x2(20); // c++98

	int x3 = { 30 }; // c++11
	int x4{ 10 }; // c++11


	auto y1 = 10; // y1 = int
	auto y2(20); // y2 = int

	auto y3 = { 30 }; // y3 = class std::initializer_list<int>
	auto y4{ 10 }; // y4 = int

	//auto 遇到 = {} 推导规则就不一样了,特殊情况 class std::initializer_list<int> C++11引入的新类型(类模板),表示某种特定的值的数组
        //class std::initializer_list<int>推导只有auto能推导出来,这一点是auto类型推导和模板类型推导的区别之处,其他和模板类型推导都差
	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(y4)>().pretty_name() << endl; //xy
	return 0; 
}

auto不适用场合举例

不能用于函数参数

不能是普通成员变量

可以是静态成员变量


#include <iostream>
#include <boost/type_index.hpp>
using namespace std;

class Test
{
public:
	//auto m_i = 12; //普通成员变量不能是auto
	static const auto m_c_s = 15; //static const静态成员可以使用auto,使用auto后,其值必须在类内初始化
							      //static const和普通静态成员不一样,普通静态成员在这里声明,在cpp中定义和初始化
								  //static cosnt静态成员就在这里定义和初始化
};

int main()
{  

	return 0; 
}

auto适用场合举例

简化代码

#include <iostream>
#include <string>
#include <map>

using namespace std;

int main()
{  

	std::map<string, int> hashmap;
	for (int i = 0; i < 10; i++)
	{
		hashmap.insert({ to_string(i), i });
	}

	/*std::map<string, int>::iterator iter;
	for (iter = hashmap.begin(); iter != hashmap.end(); ++iter)
		cout << iter->first << " " << iter->second << endl;*/



	for (auto iter = hashmap.begin(); iter != hashmap.end(); ++iter)
		cout << iter->first << " " << iter->second << endl;

	return 0; 
}



无法确定类型


#include <iostream>
#include <string>
#include <map>

using namespace std;



class A
{
public:
	static int test_a()
	{
		return 0;
	}
};


class B
{
public:
	static double test_a()
	{
		return 10.5f;
	}
};

template<typename T>
auto func()
{
	auto value = T::test_a();
	return value;
}

int main()
{  
	cout << func<A>() << endl;
	cout << func<B>() << endl;
	return 0; 
}

posted @ 2020-08-08 12:07  NaughtyCoder  阅读(969)  评论(0)    收藏  举报