auto的优势

本文讨论了C++中auto关键字的使用,强调了它在简化代码、提升效率和减少错误方面的作用。提倡在大多数情况下使用auto,特别是在处理模板、lambda表达式和复杂类型时。然而,也提醒注意潜在的类型推断错误、内存分配问题和隐式转换带来的效率损失。文章通过实例展示了auto如何简化复杂类型声明,并对比了auto与std::function的优劣,指出auto在某些场景下能更好地平衡简洁性和性能。
摘要由CSDN通过智能技术生成
  1. 总览

    • 主旨

      • 大多数都推荐用auto,少数情况还是要用显式声明.
    • 主要内容

      • 养成声明并初始化的习惯.
      • auto的代码更简洁.
      • auto可以声明未知类型变量.
      • autostd::function的好处.
  2. 必须赋值

    • 说明

      • 变量声明的时候就给赋值,可以一定程度上避免错误.
      • 声明并赋值效率可能并不高,不过代码更严谨.所以一般推崇使用的地方声明并定义.
    • 效果

      • 不初始化编译不通过,编译阶段的检查.
    • 案例一

      int main() {
         auto a;
         return 0;
      }
      
      • 编译不通过,auto必须赋值。养成定义并赋值的好习惯。
  3. 复杂变量类型简单化

    • 说明

      • 复杂的内置变量类型声明很长一串,还不一定对.用auto比较合适.
    • 案例一

      #include<vector>
      template <typename Iter>
      void foreach(Iter b, Iter e) {
         while (b != e) {
             std::iterator_traits<Iter>::value_type value = *b;
             b++;
         }
      }
      int main() {
         char s[10];
         foreach(s, s + 10);
         return 0;
      }
      
      • 编译报错,一大串的从属类型,必须用typename关键字声明后面的是类型而不是变量名才可以.
    • 案例二

      #include<vector>
      template <typename Iter>
      void foreach(Iter b, Iter e) {
         while (b != e) {
             typename std::iterator_traits<Iter>::value_type value = *b;
             b++;
         }
      }
      int main() {
         char s[10];
         foreach(s, s + 10);
         return 0;
      }
      
      • 一大长传,还不一定对。可能还会涉及到拷贝.
    • 案例三

      #include<vector>
      template <typename Iter>
      void foreach(Iter b, Iter e) {
         while (b != e) {
             auto value = *b;
             b++;
         }
      }
      int main() {
         char s[10];
         foreach(s, s + 10);
         return 0;
      }
      
      • 没有复杂的类型声明,很简单的解决了问题。
  4. lambda

    • 说明

      • lambda是一个局部类型,类型和变量名和所在环境相关.
      • 命名也不一样,可以通过反汇编或者objdump -d查看对应符号名.
    • 案例一

      int main() {
         auto s = []() {};
         decltype(s) t = s;
         return 0;
      }
      
      • 成功,类型推导赋值。
    • 案例二

      int main() {
         auto s = []() {};
         s = []() {};
         return 0;
      }
      
      • 编译错误,类型不匹配.
      template<typename T>
      void show(T&& t) {
         t.error();
      }
      int main() {
         auto s = []() {};
         auto p = []() {};
         show(s);
         show(p);
         return 0;
      }
      
      • 编译的结果是,两个类型不一样,是一个hash值.
    • 案例三

      int main() {
         auto s = [](int a,int b) {};
         return 0;
      }
      
      • C++11的简单版本。
      int main() {
         auto s = [](auto a,auto b) {};
         return 0;
      }
      
      • C++14的更简单版本,特别是在函数特别复杂的时候.
  5. autostd::function更优

    • 说明

      • 有时候一个变量用std::function存储,可能会因为存不下而分配额外的内存来存储,内存分配就可能失败.
      • 而且执行效率低.
    • 案例一

      #include<functional>
      int main() {
         std::function<void(int,int)> c = [](int a, int b) {};
         c = [](int a, int b) {};
         return 0;
      }
      
      • 编译成功。前面的两个lambda会失败,因为是随机类型,但是这里不会.
      • 但是这里同样会声明类型,而且很可能也是一大串。在简洁和执行效率上就比不上auto.
  6. 溢出

    • 说明

      • 自己定义的类型并不是返回的类型.
      • 不同平台就可能出错.
    • 案例一

      #include<vector>
      int main() {
         std::vector<int> s{ 1,2,3,4,5 };
         int t = s.size();
         return 0;
      }
      
      • 32编译成功,但是在64就可能不会成功,会编译警告.
      • 这是因为64使用的是long并不是int.
      • 就会导致溢出问题.
  7. 隐式转换

    • 主要是类型不一致,导致了隐式转换生成了拷贝版本.效率低。
  8. 总结

    • 推荐用,方便,节约内存.

    • 推荐不是强制,有的地方也建议用直接声明.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值