欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++ 11 decltype 与auto

程序员文章站 2024-03-23 10:57:40
...

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++ c++ c++11