C++ 11 decltype 与auto
c++11 新特性中,用的比较多的应该是类型推导了,类型推导有两种,auto与decltype,先说说auto.
1: auto
auto在使用时,最需要注意的应该auto会去掉CV(const , volatile)属性与引用,细说的话有三种情况:
1:auto 后没有引用或指针
int a = 1;
const int ca = 1;
const int &caref = 1;
auto a1 = a;
auto a2 = ca;
auto a3 = caref;
template<typename T>
void f(T para);
f(a);
f(ca);
f(caref);
上述的auto, 都被推导为int,事实上,auto类型推导与模板类型推导是一样的,上面的模板函数T,也都会被推导为int。这其实是合理的。这里有一点值得注意:
int a[10];
auto b = a;
template<typename T>
f(T para);
f(a);
这里会发送类型退化,即auto 和T被推导成int*,对于传递函数来说也会发生类型退化,退化成函数指针。
还有一点不同的就是std::initializer_list,由于c++11为了支持统一初始化,现在POD 类型也可用花括号初始化:
auto a = {1} // std::initalizer_list<int>
auto b(1); // int;
但是模板推导的话,不会假设这是std::initalizer_list,而是报错,这是auto与模板的不同。
2:auto后有引用,但不是万能引用:
int a = 1;
const int ca = 1;
const int &caref = 1;
auto& a1 = a; // int &
auto& a2 = ca; //const int &
auto& a3 = caref; // const int &
template<typename T>
void f(T& para);
f(a); // int &
f(ca); // const int &
f(caref); // const int &
auto与模板是一样的,带引用的话就会带上CV属性,有时可能会对a3的推导产生疑惑,因为auto后面有个引用,caref 本身有个引用,好像auto最终应该有两个引用,这里是因为有引用折叠。 对于数组类型,这里不会发生类型退化,而是会变成:
int a[10];
auto &a2 = a; // int (&)[10];
这里推导的类型是完整的,带长度信息的,对于模板推导也是如此,由此可以实现一个函数,如同sizeof:
template<typename T, size_t N>
constexpr size_t arraySize(T (&)[N]) {
return N;
}
这里也是在编译时计算,和sizeof效果一样。
3 auto后跟万能引用
int a = 1;
const int ca = 1;
const int &ra = ca;
auto&& ref1 = a; // int&
auto&& ref2 = ca; // const int &
auto&& ref3 = ra; // const int&
auto&& ref4 = 1; // int &&
这里和万能引用的推导是一样的。
2: decltype
declytype与 auto 推导规则不一样,decltype 不会去掉CV属性,而是会推导出和原来变量类型一模一样的类型。比如:
const int i;
decltype(i) a = 1;
这里的a 就是const int;
值得注意的是对于容器类操作,或者说会产生左值的操作,decltype都会推导出引用,比如:
vector<int> vec;
decltype(vec[0]); // int&
int a;
decltype((a)); // 两个括号,一个括号是左值表达式,所以推出int&
这有时可能是有问题的,比如对于vector<bool>, decltype(vec[0])的话,返回的不是bool&,而是vector内部实现的一种代理类,因为vector对bool类型有优化,为了对用户屏蔽,返回了一种代理类,通过代理类去读写,然而decltype会直接推导成代理类。
在c++14中有个写法:
int a = 1;
const int& ref = a;
decltype(auto) ref2 = ref; // const int&;
这表示需要类型推导,但使用decltype的推导规则,这常见于函数返回值的推导。
有时类型推导到底推出什么了,可能不会 确定,这是可以试试typeid(T).name();
上一篇: C++ auto与decltype