C++11引入的新关键字decltype
·
decltype主要作用就是帮助开发者在不能直接写出变量类型的时候,让编译器自动推导变量的类型。
核心作用是在编译期间推导表达式的类型,并且推导过程中不会执行表达式,仅分析其类型信息。
decltype的语法格式:
decltype (表达式) 变量名; // 括号内的表达式可以是变量、函数调用、运算式等,不能是未定义的标识符
并且其推导结果完全匹配表达式的“原生类型”(包括const、volatile。引用等)
其包括三类典型推导
1、表达式为普通变量或字面量
int a = 10;
const double b = 3.14;
decltype(a) x; // x类型为int
decltype(b) y = 2.5; // y类型为const double
// y = 6.6; // 编译器会报错,assignment of read-only variable ‘y’
decltype(5) z; // z类型为int (5是int 字面量)
2、表达式为函数调用
// 以下只是函数声明,没有定义,也证明了decltype仅分析返回值类型,并不会执行表达式
int func1();
const int func2();
decltype(func1()) a; // a类型为int
decltype(func2()) b; // b类型为const int
3、表达式为左值/右值
若表达式是左值(可被取地址的对象,如变量、数组元素、解引用指针等),推导为“该类型的引用”。
若表达式是右值(临时值,如字面量、运算结果、临时对象等),推导为“该类型本身”。
int a = 10;
int arr[5] = {1, 2, 3, 4, 5};
// 左值:推导为引用
decltype(a) x = a; // a是左值,但属于“普通变量”,所有类型还是int
decltype((a)) x1 = a; // (a)为左值表达式,推导为int&(引用)
decltype(arr[0]) x2 = arr[0]; // arr[0]为左值表达式,推导为int&(引用)
decltype(*(int*)0) x3 = a; // *(int*)a为左值表达式,推导为int&(引用)
// 右值:推导为原类型
int foo();
// 函数调用返回临时值,推导为int
decltype(foo()) y;
// 10 + 20 为临时结果,推导为int
decltype(10 + 20) y1;
关键应用场景
1、推导复杂类型(替代typedef和using)
当类型过于复杂时,decltype可以简化类型定义。这一点与auto相似,不过auto必须结合变量初始化,不能直接推导表达式类型。
// 复杂类型:vector<int> 的迭代器
std::vector<int> vec;
decltype(vec.begin()) it = vec.begin(); // it 类型为 std::vector<int>::iterator
2、 结合auto定义“返回值后置”的函数
// 函数返回两参数的“共同类型”(依赖 a 和 b 的类型)
template <typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) {
return a + b;
}
// 调用示例:a=1(int),b=2.5(double),返回类型为 double
auto result = add(1, 2.5);
decltype(add(a, b)) c = add(1, 3.14); // 推导为double
3、模板中推导模板参数类型
template <typename T>
void printSize(T container) {
// 推导容器元素的类型
decltype(container[0]) elem = container[0];
std::cout << "元素类型大小:" << sizeof(elem) << std::endl;
}
// 调用:container 为 vector<double>,elem 类型为 double&
std::vector<double> vec = {1.1, 2.2};
printSize(vec);
另外,看一下decltype和auto的区别
两者的核心区别在于类型推导依据的不同:auto依据变量的初始化表达式来推导类型,decltype依据给定的表达式本身推导类型,且不执行表达式。
而且,decltype推导时会完整保留表达式的类型属性(const、volatile),而auto的推导结果会忽略表达式的“引用性和顶层const”。
注:顶层const:指const直接修饰变量本身,影响变量的赋值行为(变量值不能被修改)
底层const:const修饰的是变量指向或引用的对象,影响对象的修改行为
比如:const int a = 5 (a是顶层const,a本身不能修改)
const int * p(p指向的是int的const, p本身可以改变指向,这是底层const)
相反,int * const p (p是顶层const)
const int a = 10;
decltype(a) b = a;
auto c = a;
b = 20; // 会报错,assignment of read-only variable ‘b’
c = 20; // c 修改成功
总结
decltype 是 C++11 引入的类型推导关键字,核心作用是依据指定表达式本身的类型进行推导,且不执行该表达式,常用于精准获取表达式类型(尤其非变量定义场景)。
更多推荐
所有评论(0)