《More Effective C++》- 极精简版 21-30条

        本文章属于专栏《业界Cpp进阶建议整理》


          继续上一篇《More Effective C++》- 极精简版 11-20条。本章我会继续讲解我对21-30条的极精简的理解。

  • 21、利用重载技术避免隐式转换
    • const A operator+(const A& a1, const A& a2) ,且有构造函数 A(int){}
    • 那 A a3 = 2 + a2;时,会先将2隐式转换为A类型的临时变量,然后调用函数。
    • 这里可以通过增加 const A operator+(int a1, const A& a2)来防止隐式转换产生临时变量
    • 但是注意,重载操作符,至少获取一个用户定制类型,不能是const A operator+(int a1, int a2)
    • 个人见解:在业务代码中,尽量使用explicit不要让隐氏转换发生。
  • 22、使用操作符,考虑用复合形式(op=)替换独身形式(op)
    • 如 +=是在自身对象上操作,没有临时对象的构造和析构。所以尽量用+=
    • 当然有时候为了代码的可读性,使用 A a1 = a2 + a3 + a4 + a5;也是可以的,在于这段代码的使用频率,是不是性能优化的重点
    • 另外为了,代码逻辑方便维护,实际加法逻辑只有一份, operator+ 调用operator+=是一个很有意义的方法。
  • 23、考虑使用其他程序库
    • 个人见解:在用三方库时,不受惯性思想,搜一下当前时间点,性能最好,最稳定的库
  • 24、了解virtual functions、multiple inheritance、virtual base classes、runtime type identification成本
    • 虚函数成本:
      • 虚函数表:每个包含虚函数的类都有一个虚函数表,表中存的是指向虚函数的地址,虚函数表的大小和虚函数个数相关。
      • 即使是多继承、或者virtual继承,虚函数本身的开销不会更大,反而是它不能inline关系更大
      • 虚函数放弃了inline(两个语义本身就冲突,虚函数运行时调用,inline编译期用函数体替换)
      • 虚函数调用就是,通过指针或者引用,找到对象的虚函数表指针,然后找到需要调用的虚函数表中的虚函数指针,执行函数。
      • 虚函数指针:每个对象都有一个虚函数指针
    • RTTI成本:
      • 作用:运行时,获取objects和classes的信息。
      • 原理:存放在每个对象的type_info结构中,这个结构由编译器生成 。一个class只需要一份RTTI,这个结构在很多编译器的实现中,放到了虚函数表中
  • 25、虚拟化构造函数和非成员函数
    • 将std::vector<Base*>的内容复制到新的vector(这里是复制内容,不是指针),不能直接调用拷贝构造函数,因为不知道具体是哪个class,这里需要一个clone函数。如基类是Base* clone() {return *this} 派生类Derive* clone() {return *this}
    • 非成员函数虚拟化,是为了多态
  • 26、限制class能产生的数量
    • 生产0个:将构造函数放到private
    • 生产1个:写一个返回对象的static函数(有static成员的函数不能用inline,每个调用函数的地方,都可能有自己的static成员变量),函数中有一个static成员
    • 生产多个:class有自己的计数器,有自己的工厂函数,有一个自己的static成员,进行计数。
      • 用一个template基类来做(注意一定要用模板基类,static计数,被所有派生类公用)
  • 27、要求、禁止对象产生于heap中
    • 要求对象必须产生在heap中,将构造函数和析构函数放到protect(private中,会影响继承)
    • 但是这样的话,派生类可以生成在栈上,其基类部分自然也在栈上
    • 想要派生类也保证只在heap上声明,利用的是operator delete,让其只删除通过operator new出来的东西,覆盖operator new(让其只从堆申请内存,并存放到类的list结构中),而delete时,去判断delete的内容是否来自于堆。
      • 这样的做法,在编译期间没有办法发现,需要在运行时候,通过异常发现(由delete抛出)
    • 个人见解:这样的需求,对于业务代码来说,有些纸上谈兵,实际中要求对象必须生产在堆中或者不在堆中,由开发者来保证是十分容易的。这样的设计模式增加的维护代价,收益却不明显。
  • 28、智能指针
    • 构造、析构和赋值容易,注意赋值需要判断是否是自己。operator()和operator->一个返回实际对象,一个返回实际指针
    • 判断存的内容是否为nullptr,调用智能指针的.get(),
    • 与继承的关系,
      • shared_ptr<Base> 和shared_ptr<Derived>不是同一类型,也不能自动转换,所以当函数参数要<Base>时,传<Derived>是不能通过编译的。
        • 对于自己写的函数,可以考虑template,这样会对不同类型的智能指针,产生实例
        • 对于历史的,没有办法改变的函数,考虑做一个拷贝 <Base> b = d,然后传入
    • 与const的关系
      • 虽然const与非const不是一个类型,但是shared_ptr<Base> b; shared_ptr<const Base> cb = b;是可以的,shared_ptr已经内部实现了
    • 个人补充:多线程对同一个智能指针对象操作是不安全的,但是智能指针对象通过复制进入各个线程,则是线程安全的
  • 29、引用计数
    • 什么时候使用引用计数
      • 引用技术是有成本的,当管理的对象越小,其相对来说代价越大。只有当引用技术带来的构造和析构的成本小时,不成为性能瓶颈,且控制数据的申请释放比较困难,我们才更愿意使用(在有限的范围内,数量不是巨大的时候,引用技术是很有意义的)
  • 30、代理类
    • 通过代理类+类型转换,区分operator[]的读和写。以在读和写时进行不同的操作。如智能指针。下面是一个简单的区分原理代码
#include <iostream>// 原始数据类
class Data {
private:int value;public:Data(int val) : value(val) {}// 代理类class Proxy {private:Data& data;public:Proxy(Data& d) : data(d) {}// 读操作operator int() const {std::cout << "Reading value: " << data.value << std::endl;return data.value;}// 写操作Proxy& operator=(int newVal) {std::cout << "Writing value: " << newVal << std::endl;data.value = newVal;return *this;}};// 返回代理类对象Proxy operator[](int index) {// 可以在这里添加索引范围检查等逻辑return Proxy(*this);}
};int main() {Data dataObj(42);// 通过代理类进行读操作int readValue = dataObj[0];std::cout << "Read result: " << readValue << std::endl;// 通过代理类进行写操作dataObj[0] = 100;return 0;
}//运行结果
//Reading value: 42
//Read result: 42
//Writing value: 100

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ctf_show笔记篇(web入门---文件上传)

文件上传 151&#xff1a;简单的前端验证&#xff0c;有多种绕过方法 152&#xff1a;简单后端验证&#xff0c;不知道过滤了那些后缀&#xff0c;我尝试以后都可以上传 153&#xff1a;利用.user.ini文件&#xff0c;虽然能上传.pht这一类文件但访问时只会下载下来 这里就…

列表吸顶分组之按首字母分组国家选区号

列表粘性分组之按首字母分组国家选区号 Android原生版本 直接先看UI图,效果如下 本来看起来也不难,我就想着上面常用区号那块不动,下面的列表滑动就行,但IOS说他滑动的时候上面也滑上去了,好吧,这也行;但最终效果做出来后,IOS滑动后会有按照国家名称首字母进行粘性分…

低代码:数智化助力新农业发展

随着科技的飞速发展和数字化转型的深入推进&#xff0c;低代码开发平台正逐渐成为软件开发的热门话题。尤其在农业领域&#xff0c;低代码技术为传统农业注入了新的活力&#xff0c;助力新农业实现高效、智能的发展。 低代码开发平台的概念与特点 随着科技的飞速发展&#xff0…

穿越数字防线:SSH协议的全景解析与未来展望

SSH基本概念 SSH&#xff08;Secure Shell&#xff09;是一个用于计算机网络的加密协议&#xff0c;设计用来提供一种安全的方式通过不安全的网络进行远程登录和其他网络服务。SSH协议主要用于远程管理系统和安全地传输信息。 SSH的历史背景 SSH由Tatu Ylnen于1995年开发&am…

IT廉连看——Uniapp——应用生命周期

IT廉连看——Uniapp——应用生命周期 [IT廉连看] 目标&#xff1a; 了解APP.vue这个页面 了解所有的应用生命周期 熟练编写常用的应用生命周期 1、App.vue&#xff1a; 在UniApp中&#xff0c;App.vue是应用的根组件。它类似于其他前端框架中的根组件&#xff0c;如Vue…

@Component和@Bean的区别

Component、Bean都是使用注解的形式来定义bean&#xff0c;从功能上讲是一样的 Component&#xff08;包括&#xff20;Service、Repository&#xff09;用于自动检测和使用类路径扫描注解&#xff0c;自动装配 bean。注解类和bean 之间是存在隐性的映射关系的&#xff0c;一个…

基于springboot的精品在线试题库系统设计与实现(程序+数据库+文档)

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 目录 一、研…

广东工行客户在手机银行上进行医保查询

现在的手机银行功能越来越多&#xff0c;对于一些不常用的功能&#xff0c;更是不知道该在哪里找到及访问&#xff0c;像医保查询&#xff0c;我原来就不知道怎么访问&#xff0c;问了别人才知道&#xff0c;特记录一下&#xff0c;以方便下次要访问时能找到。 1、从 手机银行…

考勤签到作业表单周期打卡评分小程序开发

表单考勤签到作业周期打卡评分小程序开源版开发 这是一款功能丰富的自定义表单统计小程序&#xff0c;涵盖信息填表、预约报名、签到打卡、活动通知、报名投票以及班级统计等多项功能。 高度灵活与自定义 该小程序为用户提供高度灵活的自定义表单系统。正文描述字段包含文本…

JSP语言基础(案例代码)

JSP基本语法 编写一个JSP页面&#xff0c;在该页面中显示当前时间 <% page language"java" contentType"text/html; charsetUTF-8" pageEncoding"UTF-8" import"java.util.*"%> <% page import"java.text.SimpleDateF…

独孤思维:打着永久免费更新的幌子,诱惑你付费

01 说一个副业圈讳莫如深的真相。 很多人贪便宜&#xff0c;外面收费几百上千的工具&#xff0c;结果有的地方只卖几十块。 当然不是同一个工具&#xff0c;背后做了阉割和限制。 所以才便宜。 更有甚者&#xff0c;打着永久免费更新的幌子&#xff0c;诱惑你付费。 然后…

马蹄集 开学季活动赛

目录 最大的平均值 门票 二阶前缀和 最大异或和 背军理 信号灯 切蛋糕 矩形 矩阵01变 运动会进行中 三连 距离平方和 最大的平均值 黄金时间限制:1秒巴 占用内存:128 M少难度: 给一个数组&#xff0c;长度为n&#xff0c;找一个长度大于等于m的子区间&#xff0c;使…

部署DNS 实战篇

二、DNS 部署 环境介绍 服务器3台、系统centos 安装软件 yum install -y bind bind-utils bind-chrootbind 主包bind-utils 客户端测试工具&#xff08;host 、dig 、nslookup&#xff09;bind-chroot chroot环境 禁锢dns服务器的工作目录caching-nameserver(rhel5提供…

【Redis】redis的基本使用

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Redis ⛺️稳中求进&#xff0c;晒太阳 Redis的概述 为什么要有redis? redis是数据库&#xff0c;mysql也是数据库&#xff0c;redis做缓存的意义就是为了减轻数据库压力 数据库为什么…

微信公众号公司主体变更怎么办?

公众号迁移的好处有哪些&#xff1f;迁移后原公众号还能用吗&#xff1f;1&#xff09;获得更多权限功能如果公众号是个人主体&#xff0c;想进行认证&#xff0c;拥有更多权限功能。例如菜单栏跳转外部链接&#xff0c;相拥有留言功能&#xff0c;服务号认证获得开发权限等。就…

平台总线式驱动开发

一、总线、设备、驱动 硬编码式的驱动开发带来的问题&#xff1a; 垃圾代码太多 结构不清晰 一些统一设备功能难以支持 开发效率低下 1.1 初期解决思路&#xff1a;设备和驱动分离 struct device来表示一个具体设备&#xff0c;主要提供具体设备相关的资源&#xff08;如…

openEuler系统远程SSH远程连接

文章目录 1. 本地SSH连接测试2. openEuler安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 欧拉操作系统(openEuler, 简称“欧拉”)是面向数字基础设施的操作系统,支持服务器、云计算、边缘openEuler是面向数字基础设施的操作系…

基于51单片机的心率体温检测系统设计

目 录 摘 要 I Abstract II 引 言 1 1 控制系统设计 2 1.1 主控系统方案设计 2 1.2 脉搏传感器方案设计 3 1.3 系统工作原理 5 2 硬件设计 6 2.1 主电路 6 2.1.1 单片机的选择 6 2.1.2 STC89C51的主要功能及性能参数 6 2.1.3 STC89C51单片机引脚说明 6 2.2 驱动电路 8 2.2.1 比…

第八篇 - 预测受众(Predictive audience)技术是如何赋能数字化营销生态的?- 我为什么要翻译介绍美国人工智能科技巨头IAB公司

IAB平台&#xff0c;使命和功能 IAB成立于1996年&#xff0c;总部位于纽约市。 作为美国的人工智能科技巨头社会媒体和营销专业平台公司&#xff0c;互动广告局&#xff08;IAB- the Interactive Advertising Bureau&#xff09;自1996年成立以来&#xff0c;先后为700多家媒…

基于springboot+vue的政府管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…