C++ 11 中的类型推导(auto 和 decltype)

Type Inference in C++ (auto and decltype)

类型推断是指在编程语言中自动推断出表达式的数据类型。在 C++ 11 之前,每种数据类型都需要在编译时显式声明,从而在运行时限制表达式的值,但在 C++ 新版本之后,包含了许多关键字,允许程序员将类型推导留给编译器本身. 
借助类型推断功能,我们可以减少编写编译器已经知道的东西的时间。由于所有类型都是在编译阶段推导出来的,编译时间略有增加,但不影响程序的运行时间。

1) auto 关键字: auto 关键字指定将被声明的变量的类型将自动从其初始化程序中扣除。在函数的情况下,如果它们的返回类型是自动的,那么它将在运行时由返回类型表达式进行评估。使用 auto 是为了避免在为容器创建迭代器时进行长时间的初始化。   

注意:使用 auto 关键字声明的变量只能在声明时初始化,否则会出现编译时错误。 

// C++ program to demonstrate working of auto
// and type inference

#include <bits/stdc++.h>
using namespace std;

int main()
{
	// auto a; this line will give error
	// because 'a' is not initialized at
	// the time of declaration
	// a=33;

	// see here x ,y,ptr are
	// initialised at the time of
	// declaration hence there is
	// no error in them
	auto x = 4;
	auto y = 3.37;
	auto ptr = &x;
	cout << typeid(x).name() << endl
		<< typeid(y).name() << endl
		<< typeid(ptr).name() << endl;

	return 0;
}

输出

i
d
Pi

注意:我们使用typeid来获取变量的类型。 

Typeid是一个运算符,用于需要知道对象的动态类型的情况。 

typeid(x).name() 返回x的数据类型,例如,它返回’i’表示整数,’d’表示双精度数,’Pi’表示整数指针等。但实际返回的名称主要是编译器依赖。 

使用 auto 是为了避免在为容器创建迭代器时进行长时间的初始化。

// C++ program to demonstrate that we can use auto to
// save time when creating iterators

#include <bits/stdc++.h>
using namespace std;

int main()
{
	// Create a set of strings
	set<string> st;
	st.insert({ "geeks", "for", "geeks", "org" });

	// 'it' evaluates to iterator to set of string
	// type automatically
	for (auto it = st.begin(); it != st.end(); it++)
		cout << *it << " ";

	return 0;
}

输出

for geeks org 

注意:即使分配了整数引用, auto 也会变成 int 类型。为了使其成为引用类型,我们使用 auto &。 

  • 返回“对 int 的引用”类型的函数:int& fun() {};
  • m 将默认为 int 类型而不是 int& 类型: auto m = fun();
  • n 将是 int& 类型,因为使用了额外的 & 和 auto 关键字: auto& n = fun();

2) decltype 关键字:它检查实体的声明类型或表达式的类型。’auto’ 允许您声明具有特定类型的变量,而 decltype 允许您从变量中提取类型,因此 decltype 是一种计算传递表达式类型的运算符。 
上述关键字及其用途的解释如下: 

// C++ program to demonstrate use of decltype
#include <bits/stdc++.h>
using namespace std;

int fun1() { return 10; }
char fun2() { return 'g'; }

int main()
{
	// Data type of x is same as return type of fun1()
	// and type of y is same as return type of fun2()
	decltype(fun1()) x;
	decltype(fun2()) y;

	cout << typeid(x).name() << endl;
	cout << typeid(y).name() << endl;

	return 0;
}

输出

i
c

下面是另一个示例来演示decltype的使用,

// C++ program to demonstrate use of decltype
#include <bits/stdc++.h>
using namespace std;

// Driver Code
int main()
{
	int x = 5;

	// j will be of type int : data type of x
	decltype(x) j = x + 5;

	cout << typeid(j).name();

	return 0;
}

输出

i

一个演示 auto 和 decltype 使用的程序 

下面是一个C++ 模板函数min_type(),它返回两个数字中的最小值。这两个数字可以是任何整数类型。返回类型是使用最少两个的类型来确定的。

// C++ program to demonstrate use of decltype in functions
#include <bits/stdc++.h>
using namespace std;

// A generic function which finds minimum of two values
// return type is type of variable which is minimum
template <class A, class B>
auto findMin(A a, B b) -> decltype(a < b ? a : b)
{
	return (a < b) ? a : b;
}

// driver function to test various inference
int main()
{
	// This call returns 3.44 of double type
	cout << findMin(4, 3.44) << endl;

	// This call returns 3 of double type
	cout << findMin(5.4, 3) << endl;

	return 0;
}

输出

3.44 
3

decltype 与 typeid

  • Decltype 在编译时给出类型信息,而 typeid 在运行时给出。
  • 因此,如果我们有一个引用(或指向)派生类对象的基类引用(或指针),decltype 会将类型作为基类引用(或指针)给出,但 typeid 将给出派生类型引用(或指针) .