decltype 使用

decltype 使用功能decltype可以将给定的表达式或变量的类型推导出来,包含引用和指针。一般用于复杂表达式作为返回值的类型推导。可以用于补足c++11的auto缺陷.编译阶段的事情,不会任何执行,表达式也不会执行。类型规则规则一:声明类型,类型包含引用就有引用,没有引用也不会自行添加。规则二:返回值则根据返回值类型确定最终类型。规则三:表达式根据默认和重载得到的最终类型。不建议特别复杂的表达式。声明类型分析案例一intmain()..

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

  1. 功能

    • decltype可以将给定的表达式或变量的类型推导出来,包含引用和指针。

    • 一般用于复杂表达式作为返回值的类型推导。

    • 可以用于补足c++11auto缺陷.

    • 编译阶段的事情,不会任何执行,表达式也不会执行。

  2. 类型规则

    • 规则一:声明类型,类型包含引用就有引用,没有引用也不会自行添加。

    • 规则二:返回值则根据返回值类型确定最终类型。

    • 规则三:表达式根据默认和重载得到的最终类型。不建议特别复杂的表达式。

  3. 声明类型分析

    • 案例一

      int main() { 
               
         int a = 0;
         decltype(a) b;
         b.error();
      }
      
      • 最终bint类型.
    • 案例二

      #include <cassert>
      int main() { 
               
         const int & a = 0;
         decltype(a) b = a;
         assert(&b == &a);
      }
      
      • 通过执行知道,ba是一个地址,是引用.
      • 而且类型基本类型也一致,所以类型是一致的.
    • 案例三

      #include<iostream>
      class T { 
               
      public:
         T() { 
                std::cout << "s"  << this << std::endl; }
         ~T() { 
                std::cout << "e" << this << std::endl; }
      };
      int main() { 
               
         const T && a = T();
         decltype(a) b = T();
         return 0;
      }
      
      • 只进行了两次的构造.
  4. 返回值推测

    • 案例一

      #include<vector>
      #include<iostream>
      template <typename T,typename I>
      auto show(T&& a, I i) -> decltype(a[i]) { 
               
         std::cout << "cool" << std::endl;
         return std::forward<T>(a[i]);
      }
      int main() { 
               
         std::vector<int> s = { 
                1,2,3,4 };
         decltype(show("123", 1)) a = 2;
         return 0;
      }
      
      • 这里就是,但是不会执行std::cout,因为并不会执行,在编译阶段确定了类型而已.
    • 案例二

      #include<vector>
      int main() { 
               
         std::vector<int> s = { 
                1,2,3,4 };
         decltype(s[1]) a;
         return 0;
      }
      
      • vector进行索引返回的是引用,引用类型必须初始化,所以报错。
  5. 复杂表达式

    • 案例一

      int main() { 
               
         decltype((1+2+3+4)) a = 1;
         return 0;
      }
      
      • 结果是int类型.
    • 案例二

      int main() { 
               
         int a = 1;
         decltype((a)) b = 1;
         return 0;
      }
      
      • 对变量进行(var)操作得到的是对应的引用类型,C++11的新特性.

      • 所以这里编译报错.
  6. decltype的真正作用

    • 组合后的返回值,复杂表达式。

    • 说明

      • std::vector进行[],返回的一般都是&类型,但是bool则例外.
      • 那么对于下面的代码,则不严谨.
    • 简单代码

      template <typename T,typename I>
      auto show(T& a, I i) ->decltype(a[i]) { 
               
         return a[i];
      }
      
      • 不好看.
    • 好看点

      template <typename T,typename I>
      auto show(T& a, I i) { 
               
         return a[i];
      }
      
      • C++14才支持,而且有点小问题.
      • 提示,auto推导,C++11仅仅支持简单的单个表达式推导,不支持复杂的组合表达式.

      • 但是C++14支持,C++14这里正常编译.

      • 但是auto不支持引用类型推导.这里是基本类型,是个右值。
    • 支持引用

      template <typename T,typename I>
      decltype(auto) show(T& a, I i) { 
               
         return a[i];
      }
      
      • auto表示类型推导,decltype表示按照decltype的规则进行,即何在一起就是支持引用类型推导。

      • 美中不足就是,这里仅仅支持了左值。虽然加一个const就可以支持右值,但是又不是这里讨论的手段,因为无法区分是操作的左值还是右值。
      • 操作左值和操作右值的意义是完全不一样的。

    • 支持右值引用

      template <typename T,typename I>
      decltype(auto) show(T&& a, I i) { 
               
         return a[i];
      }
      
      • 支持右值,但是这里的a是左值,非匿名消亡值.
      • a[i]返回引用,show执行完就消亡,那么会导致引用悬空.
    • 完善最终版

      template <typename T,typename I>
      decltype(auto) show(T&& a, I i) { 
               
         return std::forward<T>(a)[i];
      }
      
      • 转化为对应类型,调用对应类型的重载。然后左值返回引用,右值返回右值变量。

      void show() && { 
               }
      void show() &{ 
               }
      
      
    • 不同修饰调用不同的函数

      • 函数名后面可以用修饰变量的修饰符修饰,&&,const,volatile,&,也可以任意组合.
      • 这些可以重载,调用会使用最匹配的版本.
      • 使用了修饰的就不能定义无修饰的版本. 即show()&就不能定义show()这种.
      • 不同修饰的可以根据语义返回不同的对象.这些函数的函数名也不一样.
  7. C++11

    • ()

      • 对一个变量加(),得到的是一个引用类型.
    • 注意

      • 返回值的时候用这种,可能会带来引用悬空的情况.
  8. 总结

    • decltype得到的是声明的类型.

    • 复杂表达式得到的是最终结果的类型,即运算后结果的声明类型.

    • C++14允许decltype(auto)组合完美的推测.C++11可以通过后置的方式达到同样的效果.C++14更加简洁.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/195527.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 使用EPPlus(C#)读写Excel

    使用EPPlus(C#)读写ExcelEPPlus是使用OpenOfficeXML格式(xlsx)读写Excel2007/2010文件的.net开发库。EPPlus支持:单元格范围、单元格样式(边框,颜色,填充,字体,数字,对齐)、图表、图片、形状、批注、表格、保护加密、数据透视表、数据验证、条件格式、VBA、公式计算等等。

  • tomcat 配置pfx证书

    tomcat 配置pfx证书server.xmltomcat根目录创建cert文件夹,把文件xx.pfx文件放进去<Connectorport=”80″protocol=”HTTP/1.1″connectionTimeout=”20000″redirectPort=”443″URIEncoding=”UTF-8″/><C…

  • drwtsn32.exe 遇到问题须要关闭。我们对此引起的不便表示抱歉

    drwtsn32.exe 遇到问题须要关闭。我们对此引起的不便表示抱歉

  • js中构造函数和普通函数的区别_函数声明和函数定义

    js中构造函数和普通函数的区别_函数声明和函数定义1、构造函数也是一个普通函数,创建方式和普通函数一样,但构造函数习惯上首字母大写2、构造函数和普通函数的区别在于:调用方式不一样。作用也不一样(构造函数用来新建实例对象)3、调用方式不一样。     a.普通函数的调用方式:直接调用person();     b.构造函数的调用方式:需要使用new关键字来调用newPerson();4、构造函数的函数名与…

  • DeepLab2:用于深度标记的TensorFlow库(2021)

    DeepLab2:ATensorFLowLibraryforDeepLabelingDeepLab2是一个用于深度标注的TensorFlow库,旨在为密集像素标注任务提供统一的、最先进的TensorFlow代码库,包括但不限于语义分割、实例分割、全景分割、深度估计,甚至视频全景分割。深度标记是指通过深度神经网络为图像中的每个像素分配预测值来解决计算机视觉问题。只要感兴趣的问题可以用这种方式表述,DeepLab2就应该达到目的。此外,此代码库包括我们最近的和最先进的深度标签研究模

  • 页面返回顶部代码_网页回到顶部代码

    页面返回顶部代码_网页回到顶部代码网站添加返回顶部有好几种,下面我简单介绍下:1使用文字添加方法最简单的是:最简单的“返回顶部”代码就是“返回顶部”(不包括引号),(0,0)代表座标,第一位是水平,第二位是垂直,(0,0)就表示网页左上角,文字部分(返回顶部)可以自由替换成自己需要的内容,比如也可以用“TOP”都可以。

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号