effective c++ 笔记 条款26-31

条款 26:尽可能延后变量定义式出现的时间

应该延后变量的定义,直到非得使用该变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初值实参为止,以此避免构造(和析构)非必要对象,还可以避免无意义的default构造行为
对于循环操作,在循环前还是中进行构造,取决于赋值操作与构造+析构操作的成本对比。循环前构造会将变量的作用域扩大,除非知道该变量的赋值成本比“构造+析构”成本低,或者对这段程序的效率要求非常高,否则建议使用循环中构造

条款27: 尽量少做转型动作

const_cast:通常被用来将对象的常量性转除
dynamic_cast:主要用来执行“安全向下转型”,要用于基类和派生类之间的类型转换,具有类型检查的功能,比static_cast安全。运行时转型,但开销大,会执行对继承体系的检查
reinterpret_cast:意图执行低级转型,实际动作(及结果)可能取决于编译器,这也就表示它不可移植
static_cast:用来强迫隐式转换,编译时进行类型转换,主要用于基本数据类型的转换、隐式转换的显式化和向上转型
尽量避免转型,特别是在注重效率的代码中避免 dynamic_casts。
如果有个设计需要转型动作,通常两种做法,一:使用容器,并在其中存储直接指向derived class对象的指针(通常是智能指针),这样就避免了上述需求。二:在base class内提供virtual函数做你想对各个派生类想做的事情。这样可以使得你通过base class 接口处理“所有可能之各种派生类”。
如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用该函数,而不需将转型放进他们自己的代码内
宁可使用C++新式转型,也不用用C的旧式,因为新式的更容易被注意到,而且各自用途专一

条款28:避免返回handles 指向对象内部成分

reference、指针、迭代器系统都是所谓的handles。函数返回一个handle,随之而来的便是“降低对象封装性”的风险。它也可能导致:虽调用const成员函数却造成对象状态被更改的风险。

Point& UpperLeft() const { return pData->ulhc; }
Point& LowerRight() const { return pData->lrhc; }

成员变量可以在外部被修改,违反 logical constness 的原则的。绝对不应该令成员函数返回一个指针指向“访问级别较低”的成员函数。
改成返回常引用可以避免对成员变量的修改

const Point& UpperLeft() const { return pData->ulhc; }
const Point& LowerRight() const { return pData->lrhc; }

但是依然会带来一个称作 dangling handles(空悬句柄) 的问题,当对象不复存在时,你将无法通过引用获取到返回的数据
最保守的做法,返回一个成员变量的副本

Point UpperLeft() const { return pData->ulhc; }
Point LowerRight() const { return pData->lrhc; }

条款29: 为“异常安全”而努力是值得的

异常安全函数(Exception-safe functions)提供以下三个保证之一:

  1. 基本承诺:如果异常被抛出,程序内的任何事物仍然保持在有效状态下,没有任何对象或数据结构会因此败坏,所有对象都处于一种内部前后一致的状态,然而程序的真实状态是不可知的,也就是说客户需要额外检查程序处于哪种状态并作出对应的处理。
  2. 强烈保证: 如果异常被抛出,程序状态完全不改变,换句话说,程序会回复到“调用函数之前”的状态。
  3. 不抛掷(nothrow)保证: 承诺绝不抛出异常,因为程序总是能完成原先承诺的功能。作用于内置类型身上的所有操作都提供 nothrow 保证。
    throw() C++11 中已经被弃用,取而代之的是noexcept关键字:
int DoSomething() noexcept;

当异常抛出时,1.不泄漏任何资源 2.不允许数据败坏;

void PrettyMenu::ChangeBackground(std::vector<uint8_t>& imgSrc) {lock(&mutex);delete bgImage;++imageChanges;bgImage = new Image(imgSrc);unlock(&mutex);
}

若在new Image函数中抛出异常,mutex会发生资源泄漏,未执行unlockbgImageimageChanges也会发生数据败坏,bgImage指向已删除对象

为做到强烈保证:

  1. 使用“资源管理类”条款13
  2. 调换代码顺序
void PrettyMenu::ChangeBackground(std::vector<uint8_t>& imgSrc) {Lock m1(&mutex);bgImage.reset(std::make_shared<Image>(imgSrc));++imageChanges;
}

删除动作只发生在新图像创建成功后,只有make_shared成功,reset才调用,delete也只在reset函数内使用

另一个常用于提供强烈保证的方法是copy and swap,为打算修改的对象做出一份副本,对副本执行修改,并在所有修改都成功执行后,用一个不会抛出异常的swap方法将原件和副本交换

void PrettyMenu::ChangeBackground(std::vector<uint8_t>& imgSrc) {Lock m1(&mutex);auto pNew = std::make_shared<PMImpl>(*pImpl);    // 获取副本pNew->bgImage.reset(std::make_shared<Image>(imgSrc));++pNew->imageChanges;std::swap(pImpl, pNew);
}

强烈保证并非对所有函数都可实现或具备现实意义

异常安全保证具有木桶效应

条款30:透彻了解inlining的里里外外

inlining函数可以免除函数调用成本的开销
inlining两种实现方式:一种是为其显式指定inline关键字,另一种是直接将成员函数的定义式写在类中
inline函数通常一定被置于头文件内,因为inlining大部分情况下都是编译期行为;template通常也被置于头文件内,因为大部分建置环境都是在编译期完成具现化动作;如果一个template具现出来的函数都应该inlined,则将此template声明为inline,否则应避免此声明
inline只是对编译器的一个申请,不是强制命令。大多数编译器如无法将要求的函数inline化,会给出一个警告信息
将大多数inlining限制在小型、被频繁调用的函数身上,以便于日后的调试和二进制升级
编译器通常不对“通过函数指针而进行的调用”实施inlining
构造函数和析构函数并不适合用于inlining,往往会引起代码的膨胀(即不要随便将构造函数和析构函数的定义体放在类声明中)
inline函数代码如发生改变,所有用到该inline函数的程序都必须重新编译
inline修饰符用于解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题
在现在的 C++ 标准中,inline作为优化建议的含义已经被完全抛弃,取而代之的是“允许函数在不同编译单元中多重定义”,使得可以在头文件中直接给出函数的实现(每个.cpp的编译都是独立的,对于每个cpp来说,都是包含了Func的声明和实现,所以在链接时不清楚到底是链接哪一个同名函数)
头文件里面定义全局变量或实现了具体的函数会报错“fatal error LNK1169: 找到一个或多个多重定义的符号”,类、结构体、函数声明等抽象的东西不会

条款 31:将文件间的编译依存关系降至最低

为了增加编译速度,应该减少类文件之间的相互依存性(include),但是类内又常常使用到其他类,不得不相互依存
解决方案是:将类的声明和定义分开(不同的头文件),声明相互依存,而定义不相依存,这样当定义需要变更时,编译时不需要再因为依赖而全部编译。即尽可能让头文件自我满足
两种方法:
Handle classes/句柄类:一个声明类,一个imp实现类,声明类中不涉及具体的定义,只有接口声明,在定义类中include声明类,而不是继承。handle类的成员函数必须通过imp指针取得对象数据,每次访问会增加一层间接性会增加开销。且imp指针必须初始化在handle类的构造函数内,指向一个动态分配得来的imp对象,指针大小和动态分配内存也会带来开销
Interface classes/接口类:在接口类中提供纯虚函数,作为一个抽象基类,定义类作为其子类来实现具体的定义。增加存储虚表指针和实现虚函数跳转带来的开销

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

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

相关文章

c++笔记理解

1.封装 &#xff08;1&#xff09;构造函数不是必须在的 可以通过行为修改属性 &#xff08;2&#xff09;private和protected区别在于继承那里要学 &#xff08;3&#xff09;类默认是私有&#xff0c;struct是共有 私有的好处&#xff1a;控制数据的有效性&#xff0c;意…

编程笔记 Golang基础 012 项目构建

编程笔记 Golang基础 012 项目构建 一、模块&#xff08;Module&#xff09;、包&#xff08;Package&#xff09;和文件二、项目结构三、VsCode项目管理四、Goland项目管理五、工作空间小结 如何构建和组织一个项目&#xff0c;是学习该语言编程的开始。 一、模块&#xff08;…

MySQL 8.0.36 WorkBench安装

一、下载安装包 百度网盘链接&#xff1a;点击此处下载安装文件 提取码&#xff1a;hhwz 二、安装&#xff0c;跟着图片来 选择Custom,然后点Next 顺着左边框每一项的加号打开到每一个项的最底层&#xff0c;点击选中最底层的项目&#xff0c;再点击传过去右边的绿色箭头&a…

Codeforces Round 530 (Div. 2)

CF1099A Snowball 题目 有一个重量为 w 的雪球正在高度为 h 的地方向下滚动。每秒它的高度会减少 1。同时在高度 i 的位置它的重量会增加 i&#xff08;包括初始位置&#xff09; 同时在滚动的路线上有 2 块石头&#xff0c;第 i 块石头的高度为 hi​&#xff0c;即雪球会在 hi…

【论文阅读|基于 YOLO 的红外小目标检测的逆向范例】

基于 YOLO 的红外小目标检测的逆向范例 摘要1 引言2 相关工作2.1 逆向推理2.2 物体检测方法 3 方法3.1 总体架构3.2 逆向标准的可微分积分 4 实验4.1 数据集和指标4.2 实验环境4.4 OL-NFA 为少样本环境带来稳健性 5 结论 论文题目&#xff1a; A Contrario Paradigm for YOLO-b…

详解 leetcode_078. 合并K个升序链表.小顶堆实现

/*** 构造单链表节点*/ class ListNode{int value;//节点值ListNode next;//指向后继节点的引用public ListNode(){}public ListNode(int value){this.valuevalue;}public ListNode(int value,ListNode next){this.valuevalue;this.nextnext;} }package com.ag; import java.ut…

[树形DP] 最长乘积链

题目 1.最长乘积链 - 蓝桥云课 (lanqiao.cn) 初始思路 对问题进行分析&#xff0c;对每个点dfs去求走不同路的最远距离与次远距离求乘积&#xff0c;时间复杂度为O(n^2) 看了答案怎么弄的优化 解题思路 总的来说 预处理&#xff08;对每个结点的信息进行统计&#xff09…

AWS无服务器直播解决方案

随着媒体系统的发展&#xff0c;越来越多的直播客户想要一个即开即用的平台&#xff0c;在不需要管理和运维底层资源的同时使用一站式的媒体平台。九河云对多家云厂商有所了解及有一定合作&#xff0c;下面将按客户的需求介绍aws的无服务器直播解决方案。 架构概述&#xff1a…

Flutter插件开发指南02: 事件订阅 EventChannel

Flutter插件开发指南02: 事件订阅 EventChannel 视频 https://www.bilibili.com/video/BV1zj411d7k4/ 前言 上一节我们讲了 Channel 通道&#xff0c;但是如果你是卫星定位业务&#xff0c;原生端主动推消息给 Flutter 这时候就要用到 EventChannel 通道了。 本节会写一个 1~…

HarmonyOS 权限 介绍

权限说明 权限等级 根据权限对于不同等级应用有不同的开放范围&#xff0c;权限类型对应分为以下三种&#xff0c;等级依次提高。 normal权限 normal 权限允许应用访问超出默认规则外的普通系统资源。 这些系统资源的开放&#xff08;包括数据和功能&#xff09;对用户隐私以及…

Unity编辑器扩展之是否勾选Text组件BestFit选项工具(此篇教程也可以操作其他组件的属性)

想要批量化是否勾选项目预制体资源中Text组件BestFit属性&#xff08;此篇教程也可以操作其他组件的属性&#xff0c;只不过需要修改其中对应的代码&#xff09;&#xff0c;可以采用以下步骤。 1、在项目的Editor文件中&#xff0c;新建一个名为TextBestFitBatchProcessor的…

日常遇到Maven出现依赖版本/缓存问题通用思路。

Maven依赖错误联想 明明自己的工程是直接从大佬哪里拉下来的&#xff0c;并且自己的setting文件也是没有问题&#xff0c;可是自己偏偏编译有问题。这里介绍一种通用解决方案&#xff0c;仅供参考。 前置排查确认 我遇到原因是在JDK升级过程中遇到的&#xff1a; java.lang.…

Linux篇:指令

一 基本常识&#xff1a; 1. 文件文件内容文件的属性 2. 文件的操作对文件内容的操作对文件属性的操作 3. 文件的类型&#xff1a; d&#xff1a;目录文件 -&#xff1a;普通文件 4. 指令是可执行程序&#xff0c;指令的代码文件在系统的某一个位置存在的。/u…

Linux---进程间通讯(上)

一、进程间通讯的目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程资源共享&#xff1a;多个进程之间共享同样的资源。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它们&#xff09;发生了某种事件&#xff0…

pytorch使用文档

torch 张量操作&#xff08;torch&#xff09; torch.tensor(): 用数据创建一个 torch.Tensor 对象。torch.from_numpy(): 从 numpy 数组创建张量。torch.zeros(), torch.ones(), torch.rand(), torch.randn(): 创建具有特定形状的全0、全1、均匀分布随机、标准正态分布随机张…

css3实现无缝滚动,鼠标经过暂停

js也可以实现&#xff0c;但css3更加的平滑和资源占用更少。下面是具体代码&#xff0c;动画要单独用一个类名&#xff0c;否则暂停估计不会生效&#xff1a; 原理&#xff1a;动画向上移动&#xff0c;目标完全消失后&#xff0c;从头开始。js实现是获取消失的部分&#xff0…

分享10款自媒体人常用ai写作工具,总有一款适合你 #其他#AI写作

你是否因为写作困顿而感到沮丧&#xff1f;是不是希望能够找到一个能给你提供无限灵感和提高创作效率的利器&#xff1f;AI写作助手就是你的绝佳选择&#xff01;现在我向大家推荐几款好用的AI写作助手&#xff0c;它们将让你的创作之旅更加流畅、富有创意。 1.七燕写作 这是一…

十二、通过色彩空间转换进行更换图片背景

项目功能实现&#xff1a;对一张白色背景的图片进行更换成蓝色背景&#xff0c;类似抠图更换背景操作 按照之前的博文结构来&#xff0c;这里就不在赘述了 一、头文件 inrange.h #pragma once#include<opencv2/opencv.hpp>using namespace cv;class INRANGE{ public:v…

入门指南:Element UI 组件的安装及使用

随着前端开发技术的不断发展&#xff0c;越来越多的开发者选择使用现成的 UI 组件库来加速项目开发并提升用户体验。其中&#xff0c;Element UI 作为一款基于 Vue.js 的组件库&#xff0c;备受开发者们的青睐。本篇博客将为大家介绍如何安装并使用 Element UI 组件&#xff0c…

华为OD机试真题-围棋的气-2023年OD统一考试(C卷)---python代码

题目&#xff1a; 代码&#xff1a; """ # 输入&#xff1a;2的倍数 第一个为行号 0-18 第二个为列号 0-18第一行为黑色 第二行为白色思路&#xff1a;先求黑色&#xff0c;进行去重棋子的位置&#xff0c;再求白色 逐个棋子求坐标。 """ d…