类和动态内存分配

.

7. 解决赋值的问题
对于由于默认赋值操作符不合适而导致的问题,解决办法是提供赋值操作符(进行深度复制)定义。
其实现与复制构造函数相似,但也有一些差别。
● 由于目标对象可能引用了以前分配的数据,所以函数应使用delete[]来释放这些数据。
函数应当避免将对象赋给自身;否则,给对象重新赋值之前,释放内存操作可能删除对象的内容。
● 函数返回一个指向调用对象的引用。
通过返回一个对象,函数可以像常规赋值操作那样,连续进行赋值,即如果S0、S1和S2都是StringBad
对象,则可以编写这样的代码:
S0 = S1 = S2:
使用函数表示法时,上述代码为:
S0.operator= (S1.operator= (s2) ) :
因此,S1.operator=(S2)的返回值是函数SO.operator=()的参数。
因为返回值是一个指向StringBad对象的引用,因此参数类型是正确的。
下面的代码说明了如何为StringBad类编写赋值操作符:
StringBad & StringBad :: operator= (const StringBad & st)

if (this == &st)
return *this:
delete [] str:
len = st.len:
str = new char [len + 1]:

// object assigned to itself
// all done
// free old string

// get space for new string

std :: strcpy (str. st.str);
return *this:

第12章 类和动态内存分配

// copy the string
// return reference to invoking object

代码首先检查自我复制,这是通过查看赋值操作符右边的地址(&s)是否与接收对象(this)的地址
相同来完成的。如果相同,程序将返回*this,然后结束。第10章介绍过,赋值操作符是只能由类成员函数
重载的操作符之一。
如果地址不同,函数将释放str指向的内存,这是因为稍后将把一个新字符串的地址赋给str。如果不
首先使用delete操作符,则上述字符串将保留在内存中。由于程序中不再包含指向该字符串的指针,因此
这些内存被浪费掉。
接卜来的操作与复制构造函数相似,即为新字符串分配足够的内存空间,然后将赋值操作符右边的对
象中的字符串复制到新的内存单元中。
上述操作完成后,程序返回*this并结束。
赋值操作并不创建新的对象,因此不需要调整静态数据成员 num_strings的值。
将前面介绍的复制构造函数和赋值操作符添加到StringBad类中后,所有的问题都解决了。例如,下
面是在完成上述修改后,程序输出的最后几行:
End of main()
"Celery Stalks at Midnight" object deleted, 4 left
"Spinach Leaves Bowl for Dollars" object deleted, 3 left
"Spinach Leaves Bowl for Dollars" object deleted, 2 left
"Lettuce Prey" object deleted. 1 left
"Celery Stalks at Midnight" object deleted, 0 left
现在,对象计数是正确的,字符串也没有被损坏。

12.1.3 改进后的新String类

有了更丰富的知识后,可以对StringBad类进行修订,将它重命名为String。首先,添加前面介绍过的
复制构造函数和赋值操作符,使类能够正确管理类对象使用的内存。其次,由于我们已经知道对象何时被
创建和释放,因此可以让类构造函数和析构函数保持沉默,不再在每次被调用时都显示消息。另外,也不
用再监视构造函数的工作情况,因此可以简化默认构造函数,使之创建一个空字符串,而不是“C++”。
接下来,可以在类中添加一些新功能。String类应该包含标准字符串函数库cstring的所有功能,才会
比较有用,但这里只添加足以说明其工作原理的功能(注意,String类只是一个用作说明的范例,而C++
标准string类的内容丰富得多)。具体地说,将添加以下方法:
int length()const { return len: }
friend bool operator< (const String &st, const String &st2);
friend bool operator> (const String astl, const String &st2);
friend bool operator == (const String &st, const String &st2);
friend operator>> (istream & is, String & st):
char & operator(] (int i):
const char & operator[] (int i) const:
static int HowMany ():
第…个新方法返回被存储的字符串的长度。接下来的3个友元函数能够对字符串进行比较。Operator>>()
函数提供了简单的输入功能:两个operator[](函数提供了以数组表示法访问字符串中各个字符的功能。静
态类方法 Howmany()将补充静态类数据成员num_string。下面来看一看具体情况。
1. 修订后的默认构造函数
需要注意的是新的默认构造函数,它与下面类似:
String: :String()

len = 0:
str = new char[1]:

str[0] = '\0':

-

// default string

390

C++Primer Plus(第五版)中文版

读者可能会问,为什么代码为:
str = new char[1]:
而不是:
str = new char:
上面两种方式分配的内存量相同,区别在于前者与类析构函数兼容,而后者不兼容。析构函数中包含
如下代码:
delete [] str:
delete[]与使用 new[]初始化的指针和空指针都兼容。因此对于下述代码:
str = new char[1]:
str{0] = '\0';
可修改为:
str - 0: // sets str to the null pointer
对于以其他方式初始化的指针,使用delete[]时,结果将是不确定的:
char words [15] = "bad idea";
char * pl= words:
char * p2 = new char;
char * p3:
delete [] pl: // undefined. so don't do it
delete [] p2: // undefined, so don't do it
delete [] p3: // undefined, so don't do it

// default string

2. 比较成员函数
在String类中,执行比较操作的方法有3个。如果按字母顺序(更准确地说,按照机器排序序列),第
一个字符串在第二个字符串之前,则Operator<()函数返回true。要实现字符串比较函数,最简单的方法是
使用标准的trcmp()函数,如果依照字母顺序,第一个参数位于第二个参数之前,则该函数返回一个负值;
如果两个字符串相同,则返回0;如果第一个参数位于第二个参数之后,则返回一个正值。因此,可以这
样使用 strcmp():
bool operator< (const String sst1, const String sst2)

if (std :: strcmp (stl.str, st2.str) > 0)
return true:
else
return false:

因为内置的>操作符返回的是一个布尔值,所以可以将代码进一步简化为:
bool operator< {const String sstl, const String sst2)

return (std :: stremp (stl.str. st2.str) < 0);

同样,可以按照下面的方式来编写另外两个比较函数:
bool operator> (const String &st1, const String &st2)

return st2.str < stl.str:

bool operatorm= (const String &stl, const String &st2)

return (std :: stremp (stl.str. st2.str) == 0);

第一一个定义利用了<操作符来表示>操作符,对于内联函数,这是一种很好的选择。
将比较函数作为友元,有助于将String对象与常规的C字符串进行比较。例如,假设answer 是String
对象,则下面的代码:
if ("love" -- answer)
将被转换为:

-

第12章 类和动态内存分配

391

if loperator == ("love". answer) )
然后,编译器将使用某个构造函数将代码转换为:
if (operator == (String ("love") , answer) )
这与原型是相匹配的。

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

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

相关文章

损失函数中正则化中的平方项的作用!!

正则化上的平方项 前言在损失函数中添加正则化项时&#xff0c;通常会使用平方项作为正则化项&#xff0c;原因主要有以下几点&#xff1a; 前言 在损失函数中添加正则化项的原因主要是为了防止过拟合。正则化是一种常用的防止过拟合的技术&#xff0c;它可以对模型的复杂度进…

企业网站需不需要用到在线客服系统?

现如今&#xff0c;企业网站已成为企业展示形象、宣传产品和服务的重要窗口。在与客户互动的过程中&#xff0c;在线客服系统发挥着越来越重要的作用。那么&#xff0c;企业网站是否需要用到在线客服系统呢? 一、在线客服系统的优势 1.提高客户满意度 在线客服系统能够实现与客…

饥荒Mod 开发(十八):Mod 添加配置选项

饥荒Mod 开发(十七)&#xff1a;手动保存和加载&#xff0c;无限重生 我们可能需要给Mod 增加一些配置&#xff0c;比如是否开启全图&#xff0c;是否禁用自动保存等等&#xff0c;代码中就可以根据这些配置来做不同的逻辑。 添加配置 需要在modinfo.lua 中添加配置代码&…

VUE实现购物商城网站前端源码

文章目录 1.设计来源1.1 登录注册页面1.2 主界面1.3 列表界面1.4 详细界面1.5 购物车界面 2.源码2.1源码目录结构2.2源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/135054910 VUE实现购物商城网站前端源码&…

0155 - Java 数组

1 数组介绍 数组可以存放多个同一类型的数据。数组也是一种数据类型&#xff0c;是引用类型。 即&#xff1a;数(数据)组(一组)就是一组数据 2 数组的使用 2.1 使用方式一 2.2 使用方式二 3 数组使用注意事项和细节 数组是多个相同类型数据的组合&#xff0c;实现对这些数据…

加速Scrum敏捷转型的必选培训机构

针对敏捷转型培训&#xff0c;有一些知名的培训公司提供专业的敏捷培训课程和认证。以下是几家备受认可的敏捷转型培训公司&#xff1a; Leangoo领歌&#xff1a; Leangoo领歌是一款永久免费的专业的敏捷开发管理工具&#xff0c;提供端到端敏捷研发管理解决方案&#xff0c;包…

带你深入解析 Compose 的 Modifier 原理 -- Modifier、CombinedModifier

Modifier 的含义 实际开发过程中&#xff0c;随处可见各种 Modifier&#xff0c;比如&#xff1a; Modifier.size() // 尺寸Modifier.width() // 宽度Modifier.height() // 高度Modifier.padding() // 间距Modifier.background() // 背景Modifier.…

2023年第四届 “赣网杯” 网络安全大赛 gwb-web3 Write UP【PHP 临时函数名特性 + 绕过trim函数】

一、题目如下&#xff1a; 二、代码解读&#xff1a; 这段代码是一个简单的PHP脚本&#xff0c;它接受通过GET请求传递的两个参数&#xff1a;‘pass’和’func’&#xff1a; ① $password trim($_GET[pass] ?? );&#xff1a;从GET请求中获取名为’pass’的参数&#xff0…

Eigen库之Quaterniond

Eigen::Quaterniond 是 Eigen C++ 库中用于表示四元数的类,四元数在计算机图形学、机器人学等领域中广泛用于表示旋转操作。四元数是一种紧凑且数值稳定的旋转表示方法。 以下是如何使用 Eigen::Quaterniond 的基本概述: 1. 包含 Eigen 库: 确保在你的 C++ 代码中包含 Ei…

C语言——内存函数的使用与模拟实现

大家好&#xff0c;我是残念&#xff0c;希望在你看完之后&#xff0c;能对你有所帮助&#xff0c;有什么不足请指正&#xff01;共同学习交流 本文由&#xff1a;残念ing 原创CSDN首发&#xff0c;如需要转载请通知 个人主页&#xff1a;残念ing-CSDN博客&#xff0c;欢迎各位…

【小白专用】php pdo sqlsrv 类,php连接sqlserver

1.找到自己版本&#xff0c;我的程序是64位的。 注意&#xff1a;ts与nts的区别&#xff0c;查看phpinfo信息&#xff0c;如下 <?phpecho phpinfo();?> 2.运行后&#xff0c;可以查看到如下数据&#xff1a; ① PHP 的版本是8.2.13&#xff1b; ② 属于线程安全版 ts…

远程多窗口和Screen用法

Termius 远程链接服务器终端时&#xff0c;经常遇到需要开多个窗口&#xff0c;另外还可能涉及到正在运行的程序一旦和服务器链接断开&#xff0c;那么程序也就停止执行了。对于单单只需要多个窗口的问题&#xff0c;建议下载一个Termius这样软件&#xff0c;比多次打开…

ForkJoinPool和ThreadPoolExecutor区别是什么?

ForkJoinPool和ThreadPoolExecutor的主要区别体现在任务执行的方式和适用的场景上。 任务执行方式&#xff1a;ThreadPoolExecutor是共享队列&#xff0c;所有任务都在一个队列中等待执行。而ForkJoinPool对于每个并行度都有独立的队列&#xff0c;每个任务都会被分配到对应的…

西门子S71200系列PLC通过PROFINET连接多功能电表

西门子S71200连接多功能电表 1、需求描述&#xff1a; 通过西门子S7-1200系列PLC&#xff0c;连接多功能电表&#xff0c;通过Modbus协议读写电表的数据。 2、方案描述&#xff1a; 桥接器的网口连接西门子S7-1200系列PLC的网口&#xff0c;串口连接到电表的485通讯口&#x…

2023美团商家信息

2023美团商家电话、地址、经纬度、评分、均价、执照...

第一节TypeScript 安装

一、TypeScript 安装 前提条件&#xff1a;我们环境中已经配置npm环境。 1、使用npm安装TypeScript 首先查看你本地是否已安装npm。打开cmd -> 输入“npm -v” 回车&#xff0c;查看输出的npm版本 上述输出代码你本地环境已经安装了npm工具&#xff0c;可以使用以下命令来…

【数据结构】并查集的简单实现,合并,查找(C++)

文章目录 前言举例&#xff1a; 一、1.构造函数2.查找元素属于哪个集合FindRoot3.将两个集合归并成一个集合Union4.查找集合数量SetCount 二、源码 前言 需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规…

文件操作学习总结

磁盘上的⽂件是⽂件。 但是在程序设计中&#xff0c;我们⼀般谈的⽂件有两种&#xff1a; 程序⽂件、数据⽂件 &#xff08;从⽂件功能的⻆度来分类 的&#xff09;。 程序⽂件 &#xff1a; 程序⽂件包括源 程序⽂件&#xff08;后缀为.c&#xff09; , ⽬标⽂件&#xff0…

产品需求分析师的职责内容(合集)

产品需求分析师的职责内容1 职责&#xff1a; 1、根据公司战略规划&#xff0c;负责妇产科相关平台产品的中长期规划; 2、组织需求调研、收集、分析、整理、提炼、用户的需求&#xff0c;分析形成可行性研究报告; 3、深入挖掘产品需求&#xff0c;管理用户及公司内部业务需求&a…

配置OSPF与BFD联动示例

1、OSPF与BFD联动 双向转发检测BFD&#xff08;Bidirectional Forwarding Detection&#xff09;是一种用于检测转发引擎之间通信故障的检测机制。 BFD对两个系统间的、同一路径上的同一种数据协议的连通性进行检测&#xff0c;这条路径可以是物理链路或逻辑链路&#xff0c;包…