编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型。然而要做到这一点并非那么容易,有时甚至根本做不到。为了解决这个问题, C++11新标准引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。 --C++ primer
auto my_new_variable = its_initial_value;
对于一个auto来说,就是通过右边的值来初始化左边的量。通过编译器来推导出左边变量的类型。auto是C++11 新引入的,而类型推到则不是,在C++的函数模板中的模板实参推断就可以完成类型推到。auto要做的就是函数模板需要做的。
对于auto,使用者往往只会关心新的变量和初始化的值是不是有相同的基本类型,而不会关心一些其他的附加属性,例如const,volatile,和左右值引用(&,&&)。因为新生成的变量和初始化它的值是独立的,当用一个顶层const的值来用auto初始化一个变量的时候,这个变量完全可以是非const的,由于这两个量是独立的,所以新生成变量的值得变化是不会影响到初始化的那个值的。
所以说,
int val = 0;
auto a = val;
auto& b = val;
const auto c = val;
const auto& d = val;
int& ir = val;
auto e = ir;
int* ip = &val;
auto f = ip;
const int ci = val;
auto g = ci;
const int& cir = val;
auto h = cir;
const int* cip = &val;
auto i = cip;
int* const ipc = &val;
auto j = ipc;
const int* const cipc = &val;
auto k = cipc;
auto l{ val };
auto m = { val };
在这些例子中,a, e, g,h的类型其实是一样的,都是int。
所以,对于一个用auto声明的变量,如果需要自己的const,&等属性,就需要的声明的时候加入这些属性,就像上面的b,c,d,他们的类型分别是int&, const int 和 const int&。
f的类型是int *,在i,j,k中顶层的const的将会被忽略,底层的const将会被保留。
所以i的类型是const int *,j的类型是int *, k的类型是const int *。
最后,l和m的类型是std::initializer_list<int> 这是auto 变量推到和模板参数推到的唯一区别。
下面的代码可以检测出变量的类型
#include <type_traits>
#include <typeinfo>
#ifndef _MSC_VER
#include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>
template <class T>
std::string
type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void(*)(void*)> own
(
#ifndef _MSC_VER
abi::__cxa_demangle(typeid(TR).name(), nullptr,
nullptr, nullptr),
#else
nullptr,
#endif
std::free
);
std::string r = own != nullptr ? own.get() : typeid(TR).name();
if (std::is_const<TR>::value)
r += " const1 ";
if (std::is_volatile<TR>::value)
r += " volatile";
if (std::is_lvalue_reference<T>::value)
r += "&";
else if (std::is_rvalue_reference<T>::value)
r += "&&";
return r;
}
由于typeid().name()不能找出变量的顶层 const和左右值引用,所以采用这段代码来找出变量的类型