新电商平台,电脑优化软件哪个好用,wordpress 返利,wordpress怎么改后台密码一#xff0c;decltype 含义和举例
decltype有啥返回啥#xff0c;auto则不一样#xff0c;auto可能会舍弃一些东西。
decltype 是 C11提出的说明符。主要作用是#xff1a;返回操作数的数据类型。 decltype 是用来推导类型#xff0c;decltype对于一个给定的 变量名或…一decltype 含义和举例
decltype有啥返回啥auto则不一样auto可能会舍弃一些东西。
decltype 是 C11提出的说明符。主要作用是返回操作数的数据类型。 decltype 是用来推导类型decltype对于一个给定的 变量名或者表达式能推导出类型
这和auto 有啥区别呢
auto a 10; 我们用10这个表达式 赋值给 a那么auto 就能推断出来 a 是intauto本身也是auto。也就是说auto 必须初始化 获得这个值才能知道具体的类型。
现在我们并不希望使用一个具体的值或者表达式 来对a进行初始化那么怎么知道a 的类型呢
decltype 就派上用场了。 decltype 特点 1.decltype 的自动类型推断会发生在编译器和auto 一样 2.decltype 不会真正计算表达式的值。 decltype 后的圆括号中是个变量 const int i 0; const int iy i; auto j1 i; //auto 的传值方式i 的引用属性和const属性都会被抛弃。j1 int auto int decltype(i) j2 15; //如果decltype 中是一个变量则变量中的const 属性会保留, j2 const int decltype(iy) j3 j2;//如果decltype中是一个变量则变量中的const属性引用属性都会保留因此 j3 const int decltype 是很循规蹈矩的有啥就返回啥。 class Teacher{
public:
int i ;
}
decltype(Teacher::i) a;//会推导出 a int
Teacher tea;
decltype(tea) tea2;// 会推导出 tea2 Teacher
decltype(tea.i) mv_i;//会推导出 mv_i的类型是 int int x 1y2;
auto z x; // z 是万能引用那么先要看x 是啥x 是左值万能引用并不是一种真正的类型万能引用要不是左值引用要不是右值引用 万能引用只是一个概念因此z 是一个 左值引用 int auto也是一个int
auto zz 100; // z 是万能引用那么先要看后面传进来的值是啥是100,100是个右值因此zz就是 右值引用 int auto 是一个int。 decltype(z) h y; //z是一个万能引用其本质是一个左值引用因此 h 引用折叠发挥作用因此h 是一个 左值引用
decltype(z) h1 y; //z是一个万能引用其本质是一个左值引用因此 h1 引用折叠发挥作用只要有一个是左值引用就是左值引用因此h1 是一个 左值引用。
decltype(zz) h2 100;//zz是一个万能引用其本质是一个右值引用因此 h2 引用折叠发挥作用两个都必须是右值引用才是右值引用因此h2是右值引用注意的是给如果写成 decltype(zz) h2 y; 就会有build error这是因为h2是右值引用只能绑定右值但是y是左值。 例子
void main() {//decltype 知识点//decltype 是 C11提出的说明符。主要作用是返回操作数的数据类型。 //1 decltype 括号里面是一个变量int a 10; //普通int *pa a;//指针int yinyonga a;//左值引用decltype(a) b;using boost::typeindex::type_id_with_cvr;cout b type_id_with_cvrdecltype(b)().pretty_name() endl; //结果是intdecltype(pa) b1;cout b1 type_id_with_cvrdecltype(b1)().pretty_name() endl; //结果是int *int c 30;double d 80.8;decltype(yinyonga) b2 c; //很显然b2是一个左值引用左值引用必须绑定左值cout b2 type_id_with_cvrdecltype(b2)().pretty_name() endl; //结果是int //decltype(yinyonga) b3 d; //build error, b3 是 int是需要绑定在一个int 的左值上的d是double类型的左值因此有build error//cout b3 type_id_with_cvrdecltype(b3)().pretty_name() endl; //结果是int decltype(a) *wnyy1;cout wnyy1 type_id_with_cvrdecltype(wnyy1)().pretty_name() endl; //decltype 会将a变成 int因此 wnyy1是int *decltype(pa) *wnyy2;cout wnyy2 type_id_with_cvrdecltype(wnyy2)().pretty_name() endl;//decltype 会将pa变成 int *因此 wnyy2是int **//decltype(yinyonga) *wnyy3;//不允许使用指向 引用的指针int a1 80909;decltype(a) wnyy4 a1;cout wnyy4 type_id_with_cvrdecltype(wnyy4)().pretty_name() endl;//decltype 会将a变成 int 因此 wnyy4是int decltype(pa) wnyy5 pa;cout wnyy5 type_id_with_cvrdecltype(wnyy5)().pretty_name() endl;//decltype 会将pa变成 int * 因此 wnyy5是int *int yingyonga2 a;decltype(yinyonga) wnyy6 yingyonga2;cout wnyy6 type_id_with_cvrdecltype(wnyy6)().pretty_name() endl;//decltype 会将yinyonga变成 int 按照引用折叠规则因此 wnyy6是int int youzhiyinyonga 231;decltype(youzhiyinyonga) wnyy7 yingyonga2;cout wnyy7 type_id_with_cvrdecltype(wnyy7)().pretty_name() endl;//decltype 会将youzhiyinyonga变成 int 按照引用折叠规则因此 wnyy7是int decltype(youzhiyinyonga) wnyy8 90;cout wnyy8 type_id_with_cvrdecltype(wnyy8)().pretty_name() endl;//decltype 会将youzhiyinyonga变成 int 按照引用折叠规则因此 wnyy8是int decltype(yingyonga2) wnyy9 yinyonga;cout wnyy9 type_id_with_cvrdecltype(wnyy9)().pretty_name() endl;//decltype 会将yingyonga2变成 int 按照引用折叠规则因此 wnyy9是int } decltype 后的圆括号中非变量是表达式 decltype 会返回 表达式的 结果类型。
decltype(8) kkk 5;//decltype是计算 表达式8的结果类型也就是 int因此KKK是int
decltype(8.0) kkk1 5;//decltype是计算 表达式8.0的结果类型也就是 float因此KKK是float void main() {//decltype 后的圆括号中非变量是表达式decltype(8) kkk 5;//decltype是计算 表达式8的结果类型也就是 int因此KKK是intdecltype(8.0) kkk1 5;//decltype是计算 表达式8.0的结果类型也就是 float因此KKK是floatusing boost::typeindex::type_id_with_cvr;cout kkk type_id_with_cvrdecltype(kkk)().pretty_name() endl; //结果是intcout kkk1 type_id_with_cvrdecltype(kkk1)().pretty_name() endl; //结果是intint a 10;int *pa a;int yinyonga a;decltype(a 10) kkk2 5;cout kkk2 type_id_with_cvrdecltype(kkk2)().pretty_name() endl; //结果是int//kkk2是 int 由于 a10这个表达式的结果是int因此kkk2是intdecltype(pa 10) kkk3 ;cout kkk3 type_id_with_cvrdecltype(kkk3)().pretty_name() endl; //结果是int//kkk3是 int* 由于 pa10这个表达式的结果是int *因此kkk3是int *//decltype(*pa) kkk4 88;//会有build errorint b 800;decltype(*pa) kkk5 b;//注意这里会有不同cout kkk5 type_id_with_cvrdecltype(kkk5)().pretty_name() endl; //结果是int//kkk5是 int //*pa 是指针pa所指向的对象而且能够给对象赋值类似 *pa 800;因此 *pa 是一个左值// *pa除了在定义变量的时候其他时间都是一个表达式。// 注意这句话如果表达式结果能够作为赋值语句左边的值那么decltype后返回的就是引用//这也是为啥 kkk4 赋值80的时候会有build error因为是int 需要一个左值而80是个右值//这种情况要专门记一下。//整理为如果decltype后面是一个非变量的表达式并且表达式能够作为等号左边内容那么他返回的类型必定一个左值引用decltype(yinyonga 10) kkk6;cout kkk6 type_id_with_cvrdecltype(kkk6)().pretty_name() endl; //结果是int//kkk6是 int 由于 yinyonga10这个表达式的结果是int 因此kkk6是int decltype(a) kkk7;cout kkk7 type_id_with_cvrdecltype(kkk7)().pretty_name() endl; //结果是int//kkk7是 int 由于 a是一个变量 a是int 因此kkk7是int decltype((a)) kkk8 b;cout kkk8 type_id_with_cvrdecltype(kkk8)().pretty_name() endl; //结果是int//kkk8是 int 由于 (a)是一个表达式注意这里a是变量(a)是表达式 且(a) 90是可以赋值的因此kkk8是int } decltype后的圆括号是个函数 //decltype后的圆括号是个函数那么decltype括号中的类型为该函数返回类型但是不会真正的去执行函数它只会看函数的返回值 void main() {//decltype后的圆括号是个函数那么decltype括号中的类型为该函数返回类型但是不会真正的去执行函数它只会看函数的返回值decltype(func62()) a 90;using boost::typeindex::type_id_with_cvr;cout a type_id_with_cvrdecltype(a)().pretty_name() endl; //结果是int// a的类型是intdecltype(func63(89,90.8)) b 90000;cout b type_id_with_cvrdecltype(b)().pretty_name() endl; //结果是int// b的类型是doubledecltype(func63) c;cout c type_id_with_cvrdecltype(c)().pretty_name() endl; //结果是int// c的类型是: double __cdecl(int,double) 有返回值有参数是一个可调用对象注意不是 函数指针//如果是函数指针应该是 double (*)(int,double)//如果是函数引用 应该是 double ()(int,double)//c的类型是可调用对象c不是类型//需要使用function 类模版来处理functiondecltype(func63) cc2 func63;functiondecltype(func63) cc3 func64;//functionc cc2 func63;//build errorc是可调用对象不是类型cc2(20, 98.8);cc3(98.9,30);
} 二 decltype 主要用途 主要是用于模版编程中。 1.在类模版中应付可变类型 //decltype 主要用途1在类模版中 应付可变类型。template class T
class Teacher60 {
public:typename T::iterator iter;//typename在这里类似重命名告知 void getbegin(T tmpc) {//...iter tmpc.begin();//...}
};//类模版偏特化
template class T
class Teacher60const T{
public:typename T::const_iterator iter;// typename在这里的含义是显式地告诉编译器//T::const_iterator是一个类型名。// 然后用这 个类型 T::const_iterator 定义一个变量 iter void getbegin(const T tmpc) {//...iter tmpc.begin();//...}
};//使用decltype()方法处理实参传递的是啥我们就定义啥
template class T
class Teacher61{
public:decltype(T().begin()) iter;// 使用decltype()指定类型//注意的是 T(),生成临时对象调用临时对象的begin()函数//但是由于被 decltype 包裹因此不会调用构造函数也不会调用begin()函数说白了decltype括号里面是函数则只是会拿 函数的返回值类型不会执行函数void getbegin(const T tmpc) {//...iter tmpc.begin();//...}
};void main() {// decltype主要用途1 应付可变类型一般decltype主要用途还是应用于模版编程中using conttype std::vectorint;conttype myarr { 10,20,30 };Teacher60conttype ct;ct.getbegin(myarr);//如果我们将 conttype改成 const std::vectorint;就会有build error//原因是我们对于 const std::vectorint,需要使用typename T::const_iterator iter 处理using conttype1 const std::vectorint;conttype myarr1 { 10,20,30 };Teacher60conttype1 ct1;ct1.getbegin(myarr1);//那么对于这种问题在C98时代需要通过 类模版特例化来实现。
//https://mp.csdn.net/mp_blog/creation/success/135431592//在C11时代可以通过 decltype 来声明类型这样就避免了使用类模版特例化处理这些问题using conttype2 const std::vectorint;conttype myarr2 { 10,20,30 };Teacher61conttype2 ct2;ct2.getbegin(myarr2);} 2.通过变量表达式抽取变量类型 //decltype 主要用途2通过变量表达式 抽取 变量类型。void main() {vectorint ac;ac.push_back(1);ac.push_back(2);vectorint::size_type vsize ac.size(); //size_type 无符号整数类型通常是 std::size_t decltype(ac) bc;//bc 的类型是vectorintusing boost::typeindex::type_id_with_cvr;cout bc type_id_with_cvrdecltype(bc)().pretty_name() endl; //结果是int//bc class std::vectorint, class std::allocatorint decltype(ac)::iterator iter;decltype(ac)::size_type vvsize ac.size();cout vvsize vvsize endl;} 3.auto 结合 decltype 构成返回 类型后置 语法
//3.auto 结合 decltype 构成返回 类型后置 语法
//先回顾一下之前学的 auto 返回类型后置语法auto func70(int a, double b) -int {//auto 在这里表示的是 函数返回类型是写在-之后的。return 0;
}
//使用decltype 自动推导。ab的返回值类型是double因此 auto 是double
auto func71(int a, double b)-decltype(a b) {return a * a b;
}//对于同名函数的处理问题int func72(int temp) {cout func72(int temp) endl;return temp 2;
}double func72(double temp) {cout func72(double temp) endl;return temp 2.80;
}template typename T
auto Func73(T temp)-decltype(func72(temp)) {return func72(temp);
}void main() {int i 90;Func73(i);double d 90.8;Func73(d);
} 4.decltype(auto)用法 C14提出 问题 用于函数返回类型
decltype(auto)把auto 理解成要推导的类型推导过程我们采用decltype //decltype(auto)一起使用
//先看问题template typename T
T func80(T v1) {v1 v1 * 2;return v1;
}template typename T
auto func81(T v1) {v1 v1 * 2;return v1;
}template typename T
auto func82(T v1) {v1 v1 * 3;return v1;
}//decltype(auto) 会让返回值是啥类型v1是 T那么整个函数的返回值也就是 T
template typename T
decltype(auto) func83(T v1) {v1 v1 * 4;return v1;
}void main() {int a 100;func80int(a) 90000;//func80的返回值是 T,是个左值因此赋值由于func80返回的就是a的引用因此相当于给a赋值90000cout a a endl;//下来我们将func80 返回值auto int b 80;func81int(b) 190000;//func80的返回值是 T,是个左值因此赋值由于func80返回的就是a的引用因此相当于给a赋值90000cout b b endl;//下来我们将func80 返回值auto int c 80;//func82int(c) 190000;//build error, 因为auto 返回的类型是intcout c c endl;int d 180;func83int(d) 8190000;//使用 decltype(auto)做为返回值cout d d endl;} 用于变量声明中 int x 90;const int y 80;auto z y; //z的类型是int因为是值传递会丢弃 const 和引用decltype(auto) z1 y;//z1的类型为const int 5.再谈 decltype ()中 是变量表达式的情况再讨论 decltype(auto) func85() {int a 90;return a;
}decltype(auto) func86() {int aa 90;return (aa);
}//坑点
void main() {//我们观察 func85 和 func86//由于func86的返回值 是用()小括号 包裹的因此会被认为是一个表达式。因此func86的返回值是int//这就有问题了因为aa是局部变量出了func86的范围就失效了} 三 总结