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)


相关推荐

发表回复

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

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