Effective C++中文版学习记录(二)

Effective C++中文版学习记录(二)

章节二:构造/ 析构/ 赋值运算

进度:12/55


文章目录

  • Effective C++中文版学习记录(二)
  • 条款05、了解C++默默编写并调用哪些函数
  • 条款06、若不想使用编译器自动生成的函数,就该明确拒绝
  • 条款07、为多态基类声明virtual析构函数
  • 条款08、别让异常逃离析构函数
  • 条款09、绝不在构造和析构过程中调用virtual函数
  • 条款10、令operator= 返回一个reference to *this
  • 条款11、在operator= 中处理“自我赋值”
  • 条款12、复制对象时勿忘其每一个成分


条款05、了解C++默默编写并调用哪些函数

这一步是编译器帮忙做的,当你创建一个类时,编译器会给这个类构造四个函数:

默认构造函数
拷贝构造函数
拷贝赋值操作符
析构函数

了解即可,但是要注意,编译器为类构建的默认拷贝构造函数是浅拷贝

所以当类需要完成某些拷贝功能时,建议自己重构一个深拷贝的拷贝构造函数

条款06、若不想使用编译器自动生成的函数,就该明确拒绝

这一条款的想法来源于此:

当建立了一个class如

class Father{
public:
...
};
Father Fa1, Fa2;
Father Fa3(Fa1);  // Shouldn't success
Fa1 = Fa2;        // Shouldn't success, either

我们并不希望父亲能够被拷贝,但是正如条款05,即便我们不写拷贝函数,编译器也会有个默认的拷贝

解决方法是将拷贝构造函数设置为private

class Father{
public:
...
private:Father(const Father&);Father& operator=(const Father&); 
};

这里只需要声明,不用实现,反正不会调用它。这样就能够拒绝编译器默认的拷贝功能了

条款07、为多态基类声明virtual析构函数

回顾一下virtual的用法:

C++的一大特性是多态,也就是可以通过派生类继承基类后,对基类中同名的函数进行重写,实现同名不同工的功能

class Father
{int a,b;
public:void test() { std::cout << 1 << std::endl;}
};class Son : public Father
{int c,d;
public:void test() { std::cout << 2 << std::endl;}
};

那么运行这样的代码,结果为
在这里插入图片描述
因为p1和p2都是Father类型的指针,调用test自然是会调用到Father的test

那如果想用p2调用到Son的test呢?两个方案:一是将p2变成Son类型的指针,二是将Father的test改成virtual型函数

class Father
{int a,b;
public:void virtual test() { std::cout << 1 << std::endl;}
};

这样,p2在调用test时,就会看p2指向的元素是谁,再调用它的test,此时也就是Son的test

那么回到条款07,为什么需要让基类的析构函数为virtual呢?

就如同上文的例子,Father的析构函数为non-virtual时,对p2进行析构会发生什么,实际上是调用了Father的析构函数

但是p2指向的是Son类型,它还包含了c、d两个int型变量,而Father的析构函数并不会处理c和d,因为Father本身没有c和d

这样就会造成内存泄漏问题

那么当Father的析构函数变成virtual时,p2在调用析构函数就会看p2指向的元素是谁

这样一来p2就会调用Son的析构函数,防止内存泄漏

条款08、别让异常逃离析构函数

这条很好理解,当析构时抛出异常,那么析构工作就会停止,此时的内存情况谁也没法说清楚到底是什么样的

所以当析构过程中捕捉到异常时,请设计成它会吞下异常,并继续完成析构动作,或者直接结束程序,防止不明确行为

条款09、绝不在构造和析构过程中调用virtual函数

看例子:

class A
{
public:A() {test();}~A() {test();}virtual void test() {...}
};class B: public A
{virtual void test() const override {...}
}class C: public A
{virtual void test() const override {...}
}int main()
{B p1;
}

此时,p1的构造首先是会调用基类的构造函数,即A的构造函数,但是A中有虚函数test,而p1的类型又是A的派生类B

那么理论上讲是不是会调用B的test呢?不会,因为在构造过程中virtual不会下降到派生类,那么这样就会导致一些不明确行为

析构函数同理,这是编译器规定的东西

所以解决方法就是,构造函数和析构函数里,不要有任何virtual函数的调用

条款10、令operator= 返回一个reference to *this

这条是为了满足连等号的使用,即a=b=c=10;这样的操作

class A
{
public:...A & operator=(const & a) {...; return *this;}
}

同理,+=和-=也可以这么做

条款11、在operator= 中处理“自我赋值”

这是为了防止诸如a=a的行为

解决方案是在operator=中加入判断条件

A & operator=(const & a)
{if(A == &a) return *this;...return *this;
}

条款12、复制对象时勿忘其每一个成分

情况一是字面意思,就是不要忘记任何一个成分,假如

class A
{
private:int a,b;
public:int c;   // new element
}

这里c是新加入的元素,此时就要注意之前写好的拷贝构造函数和operator=有没有处理c这个元素

情况二是基类与派生类的关系,比如用class B继承A,并且为B构建拷贝函数,那么A中的private元素可能就没法拷贝

因为没法访问到

所以考虑调用A的拷贝函数后,再针对B的额外元素进行补充

而为了保证安全,最好是构造一个init函数来实现这两个拷贝函数的共同操作部分

避免使用A的拷贝函数实现B的拷贝函数这样的操作

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

掌握这一招,轻松用Vue和ECharts打造炫酷雷达图——详细教程指南

大家好&#xff0c;今天我要分享的是如何使用ECharts来绘制雷达图。雷达图是一种常用的数据可视化工具&#xff0c;特别适合展示多个量化指标的比较&#xff0c;也可以进行多维度用户行为分析。接下来&#xff0c;我将一步步教大家如何通过ECharts来实现这一效果。效果图如下&a…

【Conda】修复 Anaconda 安装并保留虚拟环境的详细指南

目录 流程图示1. 下载 Anaconda 安装程序2. 重命名现有的 Anaconda 安装目录Windows 操作系统Linux 操作系统 3. 运行新的 Anaconda 安装程序Windows 操作系统Linux 操作系统 4. 同步原环境使用 robocopy 命令&#xff08;Windows&#xff09;使用 rsync 命令&#xff08;Linux…

如何正确输入IP地址前面的斜杠:详细指南

在网络配置和文档编写中&#xff0c;经常需要准确地输入IP地址及其子网掩码。IP地址前面的斜杠&#xff08;/&#xff09;用于表示子网掩码的位数&#xff0c;是一个重要的组成部分。然而&#xff0c;对于一些用户来说&#xff0c;输入这个斜杠可能会带来一些困惑。本文将详细介…

Session会话管理技术

Session会话管理技术 会话: 两个交互,在开发中是指浏览器和服务器它们两个的交互 会话管理: 管理会话中产生的数据,一般是记录登录状态 补充: 状态管理,就是管理数据 1、 Session概述 Session用于记录用户的状态。Session指的是在一段时间内&#xff0c;单个客户端与Web服务…

Leetcode 1283. 使结果不超过阈值的最小除数

1.题目基本信息 1.1.题目描述 给你一个整数数组 nums 和一个正整数 threshold &#xff0c;你需要选择一个正整数作为除数&#xff0c;然后将数组里每个数都除以它&#xff0c;并对除法结果求和。 请你找出能够使上述结果小于等于阈值 threshold 的除数中 最小 的那个。 每…

在登陆功能中添加Redis缓存

目录 基于Redis实现短信登录 实现流程图 实现代码 解决登录状态刷新问题 初始方案思路&#xff1a; 实现代码 发送验证码 登陆实现 如果是新用户则自动创建 运行测试 基于Redis实现短信登录 实现流程图 实现代码 Overridepublic Result login(LoginFormDTO loginForm…

初识动态规划一>第 N 个泰波那契数

1.题目&#xff1a; 2.解析&#xff1a; 动态规划解题模板解释&#xff1a; 本题&#xff1a; 1.状态方程&#xff1a;dp[i]第i个泰波那契数 2.状态转移方程&#xff1a;根据题意得&#xff1a;把Tn3 Tn Tn1 Tn2&#xff0c; 变为Tn Tn-3 Tn-2 Tn-1。 3.初始化&#xff…

react-问卷星项目(6)

实战 React常用UI组件库 Ant Design国内最常用组件库&#xff0c;稳定&#xff0c;强大Material UI国外流行TailWind UI 国外流行&#xff0c;收费 Ant Design 官网地址 这一章基本内容就是使用UI重构页面&#xff0c;也没有什么知识点&#xff0c;直接上代码 下载 npm ins…

[Linux]:线程(三)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;Linux学习 贝蒂的主页&#xff1a;Betty’s blog 1. POSIX 信号量 1.1 信号量的概念 为了解决多执行流访问临界区&#xff0c…

Nuxt.js 应用中的 app:mounted 钩子详解

title: Nuxt.js 应用中的 app:mounted 钩子详解 date: 2024/10/5 updated: 2024/10/5 author: cmdragon excerpt: app:mounted 钩子在 Vue 应用的生命周期中扮演着重要角色,提供了在组件被挂载后的执行时机。通过合理利用这个钩子,我们能够提高组件的交互性、用户体验以及…

华为OD机试 - 核酸最快检测效率 - 动态规划、背包问题(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

基于单片机的智能浇花系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机&#xff0c;采样DHT11温湿度传感器检测温湿度&#xff0c;通过LCD1602显示 4*4按键矩阵可以设置温度湿度阈值&#xff0c;温度大于阈值则开启水泵&#xff0c;湿度大于阈值则开启风扇…

基于STM32的智能窗帘控制系统设计

引言 本项目将基于STM32微控制器设计一个智能窗帘控制系统&#xff0c;用户可以通过按钮或遥控器控制窗帘的开关&#xff0c;并且系统能够根据光照强度自动调节窗帘的开合状态。该项目展示了STM32微控制器在家居自动化中的应用&#xff0c;以及与光照传感器、直流电机和红外接…

Linux网络编程 -- 网络基础

本文主要介绍网络的一些基础概念&#xff0c;不涉及具体的操作原理&#xff0c;旨在构建对网络的基础认识。 1、网络的早期发展历程 20世纪50年代 在这一时期&#xff0c;计算机主机非常昂贵&#xff0c;而通信线路和设备相对便宜。为了共享计算机主机资源和进行信息的综合处…

模拟器GSN3之DHCP动态分配IP地址配置案例

前文《详解DHCP服务工作原理及配置案例》介绍了DHCP服务工作原理&#xff0c;要想彻底理解、应用DHCP服务&#xff0c;须通过实证案例学习&#xff0c;该文在GSN3虚拟环境下&#xff0c;构建DHCP服务的环境。 一、配置环境&#xff1a; 1、GSN3 2、路由器&#xff1a;R1、R2…

冥想第一千三百零一天(1301)

1.今天上午溪溪和小侄子写作业&#xff0c;我带着桐桐去了惠济区的裕华广场永辉&#xff0c;给家人买了好吃的&#xff0c;下午4点半左右去了妈妈朋友家里摘石榴。 2.感谢父母&#xff0c;感谢朋友&#xff0c;感谢家人&#xff0c;感谢不断进步的自己。

[C++]使用纯opencv部署yolov11旋转框目标检测

【官方框架地址】 GitHub - ultralytics/ultralytics: Ultralytics YOLO11 &#x1f680; 【算法介绍】 YOLOv11是一种先进的对象检测算法&#xff0c;它通过单个神经网络实现了快速的物体检测。其中&#xff0c;旋转框检测是YOLOv11的一项重要特性&#xff0c;它可以有效地检…

利用 Python 爬虫采集 1688商品详情

1688是中国的一个大型B2B电子商务平台&#xff0c;主要用于批发和采购各种商品。对于需要从1688上获取商品详情数据、工程数据或店铺数据的用户来说&#xff0c;可以采用以下几种常见的方法&#xff1a; 官方API接口&#xff1a;如果1688提供了官方的API接口&#xff0c;那么可…

FinOps现状分析:行业趋势与未来展望

一、FinOps 的国内现状 《FinOps 现状》是 FinOps 基金会自 2020 年以来开展的一项年度调查&#xff0c;旨在收集对关键优先、行业趋势和 FinOps 实践方向 的见解。该调查有助于为 FinOps 基金会的活动提供信息&#xff0c;并为更广泛的市场提供有关 FinOps 在各种组织中如何实…

redhat7.7 linux 网络配置文件

一、为什么虚拟网卡配置文件是ens33 变更目录至网络脚本&#xff08;network-scripts&#xff09;文件夹&#xff0c;发现网络配置文件名称为“ifcfg-ens33” cd /etc/sysconfig/network-scripts ls扩展&#xff1a;“ifcfg-ens33”文件下面还有一个“ifcfg”前缀的文件&…