【Effective Modern C++】第2章 auto

【Effective Modern C++】第2章 auto

auto好处:少打一些字,阻止那些由于手动指定型别带来的潜在错误和性能问题

条款5:优先选用auto,而非显示型别声明

  • 使用auto必须初始化,就可以避免一系列由未初始化带来的问题

  • auto用在lambda表达式的形参类型声明中,并且可以声明变量直接持有闭包,如:

    auto derefLess =                                //C++14版本
        [](const auto& p1,                          //被任何像指针一样的东西
           const auto& p2)                          //指向的值的比较函数
        { return *p1 < *p2; };
    
  • 你可能会想我们完全不需要使用auto声明局部变量来保存一个闭包,因为我们可以使用std::function对象。

    std::function<bool(const std::unique_ptr<Widget> &,
                       const std::unique_ptr<Widget> &)>
    derefUPLess = [](const std::unique_ptr<Widget> &p1,
                     const std::unique_ptr<Widget> &p2)
                    { return *p1 < *p2; };
    

    语法冗长不说,还需要重复写很多形参类型,使用std::function还不如使用auto。用auto声明的变量保存一个和闭包一样类型的(新)闭包,因此使用了与闭包相同大小存储空间。实例化std::function并声明一个对象这个对象将会有固定的大小。这个大小可能不足以存储一个闭包,这个时候std::function的构造函数将会在堆上面分配内存来存储,这就造成了使用std::functionauto声明变量会消耗更多的内存。换句话说,std::function方法比auto方法要更耗空间且更慢,还可能有out-of-memory异常。

  • auto还可以避免一类“型别捷径”的问题。v.size()的标准返回类型是std::vector<int>::size_type,但是只有少数开发者意识到这点。std::vector<int>::size_type实际上被指定为无符号整型,所以很多人都认为用unsigned就足够了,举个例子,在Windows 32-bitstd::vector<int>::size_typeunsigned是一样的大小,但是在Windows 64-bitstd::vector<int>::size_type是64位,unsigned是32位。这意味着这段代码在Windows 32-bit上正常工作,但是当把应用程序移植到Windows 64-bit上时就可能会出现一些问题。谁愿意花时间处理这些细枝末节的问题呢?所以使用auto可以确保你不需要浪费时间:

    auto sz =v.size();                      //sz的类型是std::vector<int>::size_type
    

    再比如,考虑下面的代码,看起来好像很合情合理的表达,但是这里有一个问题,你看到了吗?

    std::unordered_map<std::string, int> m;for(const std::pair<std::string, int>& p : m)
    {//用p做一些事
    }
    

    要想看到错误你就得知道std::unordered_mapkeyconst的,所以hash tablestd::unordered_map本质上的东西)中的std::pair的类型不是std::pair<std::string, int>,而是std::pair<const std::string, int>。但那不是在循环中的变量p声明的类型。编译器会努力的找到一种方法把std::pair<const std::string, int>(即hash table中的东西)转换为std::pair<std::string, int>p的声明类型)。它会成功的,因为它会通过拷贝m中的对象创建一个临时对象,这个临时对象的类型是p想绑定到的对象的类型,即m中元素的类型,然后把p的引用绑定到这个临时对象上。在每个循环迭代结束时,临时对象将会销毁,如果你写了这样的一个循环,你可能会对它的一些行为感到非常惊讶,因为你确信你只是让成为p指向m中各个元素的引用而已。

    使用auto可以避免这些很难被意识到的类型不匹配的错误:

    for(const auto& p : m)
    {//如之前一样
    }
    

    这样无疑更具效率,且更容易书写。而且,这个代码有一个非常吸引人的特性,如果你获取p的地址,你确实会得到一个指向m中元素的指针。在没有auto的版本中p会指向一个临时变量,这个临时变量在每次迭代完成时会被销毁。

  • 关于使用auto代替传统类型声明对源码可读性的影响的问题,放松,auto可选项,不是命令,在某些情况下如果你的专业判断告诉你使用显式类型声明比auto要更清晰更易维护,那你就不必再坚持使用auto

  • 事实是显式指定类型通常只会引入一些微妙的错误,无论是在正确性还是效率方面。而且,如果初始化表达式的类型改变,则auto推导出的类型也会改变,这意味着使用auto可以帮助我们完成一些重构工作。

要点速记

  • auto变量必须初始化,通常它可以避免一些移植性和效率性的问题,也使得重构更方便,还能让你少打几个字。
  • auto型别的变量都有着条款2和条款6中所述的毛病。

条款6:当auto推导的型别不符合要求时,使用带显式型别的初始化物习惯用法

  • std::vector<bool> features(const Widget& w);
    //bool highPriority = features(w)[5];
    auto highPriority = features(w)[5];		// !!!,highPriority的型别不再是bool了
    processWidget(w,highPriority);          //未定义行为!
    

    虽然从概念上来说std::vector<bool>意味着存放bool,但是std::vector<bool>operator[]不会返回容器中元素的引用(这就是std::vector::operator[]可返回除了bool以外的任何类型),取而代之它返回一个std::vector<bool>::reference的对象(一个嵌套于std::vector<bool>中的类)。std::vector<bool>::reference之所以存在是因为std::vector<bool>规定了使用一个打包形式(packed form)表示它的bool,每个bool占一个bit。那给std::vectoroperator[]带来了问题,因为std::vector<T>operator[]应当返回一个T&,但是C++禁止对bits的引用。

    无法返回一个bool&std::vector<bool>operator[]返回一个行为类似于bool&的对象。要想成功扮演这个角色,bool&适用的上下文std::vector<bool>::reference也必须一样能适用。在std::vector<bool>::reference的特性中,使这个原则可行的特性是一个可以向bool的隐式转化。(不是bool&,是**bool**。)

  • std::vector<bool>::reference是一个代理类(proxy class)的例子:所谓代理类就是以模仿和增强一些类型的行为为目的而存在的类。一些代理类被设计于用以对客户可见。比如std::shared_ptrstd::unique_ptr。其他的代理类则或多或少不可见,比如std::vector<bool>::reference就是不可见代理类的一个例子,还有它在std::bitset的胞弟std::bitset::reference
    一个普遍的规律是,“隐形”代理类和auto无法和平共处。这种类的对象往往会设计成仅仅维持到单个语句之内存在。所以以下的代码可能会导致未定义的i行为,要防止写出这样的代码:

    auto someVar="隐形"代理型别表达式
    

    那么如何发现使用了代理类呢,一是查看接口文档,二是查看头文件的函数签名。这个问题并不是放弃使用auto的理由,解决方案应该是进行另一次型别转换,如使用static_cast就可以表明“我故意转为了某种类型”。

    auto index = static_cast<int>(d * size());
    

要点速记

  • “隐形”的代理类可能会使auto从表达式中推导出“错误的”类型
  • 显式类型初始器惯用法强制auto推导出你想要的结果

参考:Effective Modern C++(中文版)和这里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/783493.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Hack The Box-PermX

总体思路 CVE-2023-4220->敏感信息收集->符号链接攻击 信息收集&端口利用 nmap -sSVC permx.htbStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-07 21:16 EDT Nmap scan report for permx.htb Host is up (0.24s latency). Not shown: 998 closed tcp po…

为什么要设计DTO类

为什么要使用DTO类&#xff0c;下面以新增员工接口为例来介绍。 新增员工 1.1 需求分析和设计 1.1.1 产品原型 一般在做需求分析时&#xff0c;往往都是对照着产品原型进行分析&#xff0c;因为产品原型比较直观&#xff0c;便于我们理解业务。 后台系统中可以管理员工信息…

供应RTL8366SC-CG瑞昱芯片

标17566722766题 长期供应各品牌原装芯片&#xff1a; RTL8366SC-CG RTL8382L-VB-CG RTL8218D-CG RTL8192EU-VP-CG RTL8821CU-CG RTL8811CU-CG RTL8723DU-CG RTL8723DS-CG RTL8711AM-VB1-CG RTL8111H-VB-CG RTL8111H-CG RTL8211F-CG RTL8211E-VB-CG RTL8733BS…

HW期间——溯源

01 前期准备 001溯源的概念 通过对受害资产与内网流量进行分析一定程度上还原攻击者的攻击路径与攻击手法根据已有的线索&#xff0c;攻击方式以及攻击特征等通过技术手段反查攻击者身份或是组织信息。 描述&#xff1a;完整还原攻击链条&#xff0c;溯源到黑客的虚拟身份&…

算法 - 动态规划

文章目录 介绍解题步骤题型背包问题01背包问题朴素算法&#xff08;递归实现&#xff09;备忘录算法(记忆化搜索)递推求解算法&#xff08;动态规划&#xff09; 连续子段和问题最大连续子序列和最大连续子序列和的最优方案 递推问题斐波那契数列II数塔II上楼II 最长不下降子序…

选项卡切换(排他法、轮转法、轮转法之事件委托)

选项卡需求&#xff1a; tabbar content 两部分的内容一一对应&#xff0c;我们点击某一个tab的时候&#xff0c;该tab的类名设置为on&#xff0c;其他的tab要清除on类名&#xff0c;对应的content的类名要设置为 active &#xff0c;其他的content清除active类名。 <!DOCTY…

vue通过后台返回的数字显示不同的文字内容,多个内容用、隔开

后台返回的数据 显示效果&#xff1a; html&#xff1a; <el-table-columnalign"center"label"使用过的小程序"width"124"v-if"activeTab 0"><template #default"scope"><divv-for"(item, index) in s…

众所周知沃尔玛1P是怎么运营?

​​沃尔玛的1P模式&#xff0c;即第一方供应商模式&#xff0c;是其独特的采购策略。在这种模式下&#xff0c;供应商先将商品卖给沃尔玛&#xff0c;由沃尔玛负责库存管理和销售。沃尔玛通过强大的采购和物流能力控制库存&#xff0c;确保商品品质&#xff0c;为客户提供更加…

【操作系统】进程管理——调度算法(个人笔记)

学习日期&#xff1a;2024.7.4 内容摘要&#xff1a;各种调度算法的思想、规则、优缺点介绍 为什么要有调度算法&#xff1f; 调度算法就好比一群人在银行办理业务&#xff0c;准备办理业务的人就是进程/作业&#xff0c;银行窗口的工作人员就是CPU&#xff0c;进程往往是比C…

旅游计划定制小程序网页模板源码

手机在线旅游定制服务&#xff0c;定制旅游出行app小程序模板。包含&#xff1a;定制介绍、定制表单填写、我的订单等。 旅游计划定制小程序网页模板源码

力扣爆刷第161天之TOP100五连刷71-75(搜索二叉树、二维矩阵、路径总和)

力扣爆刷第161天之TOP100五连刷71-75&#xff08;搜索二叉树、二维矩阵、路径总和&#xff09; 文章目录 力扣爆刷第161天之TOP100五连刷71-75&#xff08;搜索二叉树、二维矩阵、路径总和&#xff09;一、98. 验证二叉搜索树二、394. 字符串解码三、34. 在排序数组中查找元素的…

idea Git操作

1、代码拉取&#xff08;左上角&#xff09; 或 2、代码push&#xff08;左上角&#xff09; 3、切换分支&#xff08;右下角&#xff09; 4、分支管理 5、当前分支和某一个分支对比差异 6、当前分支某一个提交需要恢复成提交前状态&#xff08;revert&#xff09; 7、其他分…

信息技术课上的纪律秘诀:营造有序学习环境

信息技术课是学生们探索数字世界的乐园&#xff0c;但同时也是课堂纪律管理的挑战场。电脑、网络、游戏等元素可能分散学生的注意力&#xff0c;影响学习效果。本文将分享一些有效的策略&#xff0c;帮助教师在信息技术课上维持课堂纪律&#xff0c;确保教学活动顺利进行。 制…

简过网:快来看看你的专业能考哪个类型的事业单位?

你的专业能考哪个类型的事业单位&#xff0c;你知道吗&#xff1f;想考事业单位的姐妹&#xff0c;一定要在备考之前&#xff0c;查清楚你的专业适不适合考事业单位、考哪类事业编以及能报考哪些岗位&#xff1f;这个才能上岸的几率更高一些&#xff01; 事业单位有5类岗位&am…

安全防御(防火墙)

第二天&#xff1a; 1.恶意程序---一般会具有一下多个或则全部特点 1.非法性&#xff1a;你未经授权它自动运行或者自动下载的&#xff0c;这都属于非法的。那恶意程序一般它会具有这种特点&#xff0c; 2.隐蔽性&#xff1a;一般隐藏的会比较深&#xff0c;目的就是为了防止…

学生护眼台灯哪个牌子实用?值得入手的学生护眼台灯十大排名分析

在这个数码时代&#xff0c;人们对屏幕的依赖程度越来越高&#xff0c;尤其是孩子们。他们不仅在学校里需要长时间盯着教科书&#xff0c;还会在学习和娱乐中使用各种数码设备。然而&#xff0c;这也使得眼睛健康问题逐渐凸显&#xff0c;尤其是儿童近视的问题。为了保护视力&a…

重庆交通大学数学与统计学院携手泰迪智能科技共建的“智能工作室”

2024年7月4日&#xff0c;重庆交通大学数学与统计学院与广东泰迪智能科技股份有限公司携手共建的“智能工作室”授牌仪式在南岸校区阳光会议室举行。此举标志着数统学院与广东泰迪公司校企合作新篇章的开启&#xff0c;也预示着学院在智能科技教育领域的深入探索和实践。 广东…

利用Python进行数据分析PDF下载经典数据分享推荐

本书由Python pandas项目创始人Wes McKinney亲笔撰写&#xff0c;详细介绍利用Python进行操作、处理、清洗和规整数据等方面的具体细节和基本要点。第2版针对Python 3.6进行全面修订和更新&#xff0c;涵盖新版的pandas、NumPy、IPython和Jupyter&#xff0c;并增加大量实际案例…

SSM高校学生综合测评系统-计算机毕业设计源码16154

摘要 随着互联网时代的到来,同时计算机网络技术高速发展,网络管理运用也变得越来越广泛。因此,建立一个BS 结构的高校学生综合测评系统,会使高校学生综合测评系统工作系统化、规范化,也会提高高校学生综合测评系统平台形象,提高管理效率。 本学生综合测评系统是针对目前高校学生…

C++第二弹 -- C++基础语法下(引用 内联函数 auto关键字 范围for 指针空值)

本篇大纲 前言一. 引用续讲1. 传值,传引用效率对比2. 类型转换和表达式传引用的注意事项3. 引用与指针 二. 内联函数1. 概念2. 特性3. 面试题 三. auto关键字(C11)1. 类型别名思考2. auto简介3. auto的使用细则4. auto不能推导的场景 四. 基于范围的for循环(C11)1. 范围for的语…