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更加简洁.

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • DeepFake技术–Deepfakes教程及各个换脸软件下载

    DeepFake技术–Deepfakes教程及各个换脸软件下载Deepfakes目前用于深度换脸的程序基本都是用python编程语言基于tensorflow进行计算。以下列出几款常用的换脸程序优缺点浅析,用户可以根据自己的爱好和水平来选择,以下软件均需要先安装windows版本的VS2015,CUDA9.0和CuDNN7.0.5(fakeapp教程,deepfakes视频deepfakes中文站(deepfakes.com.cn))下面几个程序的对比…

    2022年5月9日
    475
  • vue集成spreadjs

    vue集成spreadjsvue 集成 spreadjs 先使用 npm 安装 spreadjs 插件然后在页面引用直接上代码效果图先使用 npm 安装 spreadjs 插件 grapecity spread excelio 14 0 10 grapecity spread sheets 14 0 10 grapecity spread sheets barcode 14 0 10 grapecity spread sheets charts 14 0 10 grapecity sp

    2025年9月24日
    7
  • 异步传输模式atm采用_什么是云主机

    异步传输模式atm采用_什么是云主机异步传输模式(ATM)也称为信元中继(在固定大小的信元中传输数据),它通过光纤或双绞线电缆(高速交换)在OSI模型的数据链路层(第2层)运行一种基于ITU-T宽带综合业务数字网(B-ISDN)标准的网络技术,该标准是由电信业开发的,用于实现下一代网络。ATM专为在WAN(如公用电话系统和公司数据网络)中使用而设计,尽管它也已被用于创建超高速LAN。ATM可以同时传输各种流量:语音,视频和数据,速度高达每秒155兆比特。它将语音,视频数据转换为数据包,并通过相同的介质传递大数据包数据。ATM与TCP/.

    2026年2月6日
    6
  • Kali2021修改更新源[通俗易懂]

    Kali2021修改更新源[通俗易懂]本次演示三种环境更换更新源Xfce4版本KDE版本命令行版本更新源#中科大debhttp://mirrors.ustc.edu.cn/kalikali-rollingmainnon-freecontribdeb-srchttp:/…

    2022年5月27日
    44
  • php开发工程师面试题知识点总结(四)–高级篇「建议收藏」

    php开发工程师面试题知识点总结(四)–高级篇

    2022年2月12日
    36
  • hibernate id 生成器「建议收藏」

    hibernate id 生成器「建议收藏」hibernateid生成器1、identity:用于MySql数据库。特点:递增 ..    .注:对于MySql数据库使用递增序列时需要在建表时对主键指定为auto_increment属性。 2、sequence:用于Oracle数据库 ..   .     序列名.   .3、native:跨数据库时使用,由底层方言产生

    2022年6月21日
    31

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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