C++学习笔记----7、使用类与对象获得高性能(二)---- 理解对象生命周期(7)

news/2024/9/22 16:50:55 标签: c++, 学习, 笔记, 开发语言

13、对象赋值

        就像在c++中可以将一个int值赋给另一个,也可以将一个对象赋值给另一个对象。例如,下面的代码将MyCell的值赋值给anotherCell:

SpreadsheetCell myCell { 5 }, anotherCell;
anotherCell = myCell;

        你可能会说是myCell被“拷贝”给了anotherCell。然而,在c++的世界里,“拷贝”只会发生在对象被初始化时。如果一个对象已经有值了被覆写,更准确的词是“赋值”。注意c++提供给拷贝的工具是拷贝构造函数。因为是构造函数,只能用于对象生成,而不能用于对象的赋值。

        因此,c++提供了另外一个成员函数在每个类中执行赋值。这个成员函数叫做赋值操作符。它的名字叫做operator=,因为它实际上是对=操作符的重载。在前面的例子中,对anotherCell调用赋值操作符,用myCell作为参数。

        在这里解释的赋值操作符有时候也叫做拷贝操作符,因为数据是从右边的对象拷贝到左边的对象。我们后面会讨论另外一种赋值操作符,move赋值操作符,数据是移动而不是拷贝,在特定使用场景下提高了性能。

        按惯例,如果你不写自己的赋值操作符,c++会为你写一个允许对象被赋值给另一个对象。缺省的c++赋值行为几乎与缺省的拷贝行为一模一样:从源到目标递归赋值每一个数据成员。

13.1、声明赋值操作符

        下面是SpreadsheetCell类的赋值操作符:

export class SpreadsheetCell
{
public:
    SpreadsheetCell& operator=(const SpreadsheetCell& rhs);
    // Remainder of the class definition omitted for brevity
};

        赋值操作符通常会用常量引用给到源对象,与拷贝构造函数差不多。在这种情况下,源对象叫做rhs,代表等号右边的,当然了,你可以给它起任何名字。赋值操作符被调用的对象是等号左边的。

        与拷贝构造函数不一样的是,赋值操作符返回一个对SpreadsheetCell对象的引用,原因是赋值可以连续,如下所示:

myCell = anotherCell = aThirdCell;

        这行代码被执行时,发生的第一件事是对anotherCell赋值操作符被用aThirdCell作为其“右边”参数进行调用。接着,myCell的赋值操作符被调用。然而,它的参数不是anotherCell;它的右边是将aThirdCell赋值给anotherCell的结果。等号只是真实成员函数调用的简化。如果你看这儿显示的函数语法,就可以看出问题:

myCell.operator=(anotherCell.operator=(aThirdCell));

        现在,可以看出operator=从anotherCell调用必须返回一个值,该值传递给了对myCell的operator=的调用。返回的正确值是对于anotherCell自身的引用,所以它可以作为myCell赋值的源。

        警告:实际上可以声明赋值操作符返回想要的任何类型,包括void。然而,总要返回对象的引用,因为客户期待其被调用。

13.2、定义赋值操作符

        赋值操作符的实现与拷贝构造函数类似,但也有一些重要的差异。首先,拷贝构造函数只在初始化时调用,所以目标对象还没有有效值。赋值操作符可以覆写对象的当前值。这种考虑直到在对象中动态分配了如内存这样的资源时才会出现,以后会详细讨论。

        其次,在C++中给对象自身赋值是合法的。例如,下面的代码能够正常编译与运行:

SpreadsheetCell cell { 4 };
cell = cell; // Self-­assignment

        赋值操作符需要把自我赋值的可能性考虑进去。在SpreadsheetCell类中,这不重要,因为它只有一个原始的数据类型double。然而,当类中有动态分配内存或者其它资源时,首先要考虑的就是自我赋值问题了,这个我们会在以后讨论。为了避免这样的问题,赋值操作符的首要任务通常是检测自我赋值,如果答案为是的话立马返回。

        下面是SpreadsheetCell类的赋值操作符的定义的起头:

SpreadsheetCell& SpreadsheetCell::operator=(const SpreadsheetCell& rhs)
{
    if (this == &rhs) {

        第一行检测是否是自我赋值,但是可能有一点绕。自我赋值发生在等号左边与右边相同的时候。一个方法是指出两个对象是否相同看它们是否占用了相同的内存地址--显式地,如果指向它们的指针是相同的。记得this是一个从任何成员函数对对象进行调用指向可访问对象的指针。这样的话,this就是一个指向左边对象的指针。同样的,&rhs是一个指向右边对象的指针。如果这些指针相同,赋值一定是自我赋值,但是,因为返回类型是SpreadsheetCell&,也要返回正确的值。所有的赋值操作符像下面一样返回*this,自我赋值的情况也不例外:

    return *this;
}

        this是一个指向成员函数执行的对象的指针,所以*this就是对象本身。编译器返回该对象的引用来匹配声明的返回类型。现在,如果它不是自我赋值的话,你就要给每一个成员进行赋值了:

    m_value = rhs.m_value;
    return *this;
}

        这儿成员函数拷贝值,最终,如前面解释的那样,返回*this。

        细心的读者会注意到在拷贝赋值操作符与拷贝构造函数之间有一些代码重复;它们都需要拷贝所有的数据成员。我们后面会介绍拷贝且交换的方法来避免这样的代码重复。

        注意:SpreadsheetCell赋值操作符这里展示的只是为了演示的目的。实际上,在这种情况下,赋值操作符可以省略,因为缺省编译器生成的已足够好;它会进行简单的成员感知的所有数据成员的赋值。然而,在特定的情况下,这种编译器生成的赋值操作符是不够的,这些情况我们以后会讨论到。

        警告:如果类要求对拷贝操作的特殊处理,要实现拷贝构造函数与拷贝赋值操作符。

13.3、显式缺省与删除赋值操作符

        可以显式缺省与删除编译器生成的赋值操作符如下:

SpreadsheetCell& operator=(const SpreadsheetCell& rhs) = default;
SpreadsheetCell& operator=(const SpreadsheetCell& rhs) = delete;


http://www.niftyadmin.cn/n/5670613.html

相关文章

【算法——双指针】

922. 按奇偶排序数组 II 算法讲解050【必备】双指针技巧与相关题目_哔哩哔哩_bilibili main:vector<int>nums { 3,1,2,4 };int i 0, j 1;int n nums.size() - 1;while (j < nums.size() && i < nums.size()) //如果奇偶任一方排好了&#xff0c;另…

Python基础 | 在虚拟环境中安装并在指定文件夹中打开Jupyter notebook

在虚拟环境中安装并在指定文件夹中打开Jupyter notebook 前言一、在虚拟环境下安装Jupyter notebook二、在指定路径下打开Jupyter notebook 前言 Jupyter Notebook 是一个基于 Web 的交互式计算环境&#xff0c;主要功能是将代码、文本、数学方程式、可视化和其他相关元素组合…

SkyWalking 环境搭建部署

架构简介 skywalking agent : 和业务系统绑定在一起,负责收集各种监控数据skywalking oapservice : 是负责处理监控数据的,比如接受skywalking agent的监控数据,并存储在数据库中;接受skywalking webapp的前端请求,从数据库查询数据,并返回数据给前端。Skywalking oapserv…

MySQL高阶之存储过程

什么是存储过程? 存储过程可称为过程化SQL语言&#xff0c;是在普通SQL语句的基础上增加了编程语言的特点&#xff0c;把数据操作语句(DML)和查询语句(DQL)组织在过程化代码中&#xff0c;通过逻辑判断、循环等操作实现复杂计算的程序语言。 换句话说&#xff0c;存储过程其实…

技术周总结 09.16~09.22 周日(架构 C# 数据库)

文章目录 一、09.16 周一1.1&#xff09;问题01&#xff1a; 软件质量属性中"质量属性场景"、"质量属性环境分析"、"质量属性效用树"、"质量属性需求用例分析"分别是什么&#xff1f;1.2&#xff09;问题02&#xff1a; 软件质量属性中…

[数据集][目标检测]文本表格检测数据集VOC+YOLO格式6688张5类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6688 标注数量(xml文件个数)&#xff1a;6688 标注数量(txt文件个数)&#xff1a;6688 标注…

王道考研视频——操作系统笔记

操作系统第一章&#xff01;入门 王道考研视频——操作系统笔记&#xff0c;第一部分&#xff0c;操作系统的概念和体系结构 0.0 课程白嫖指南_哔哩哔哩_bilibili0.0 课程白嫖指南是王道计算机考研 操作系统的第1集视频&#xff0c;该合集共计84集&#xff0c;视频收藏或关注UP…

刷题训练之栈

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握字符串算法。 > 毒鸡汤&#xff1a;学习&#xff0c;学习&#xff0c;再学习 ! 学&#xff0c;然后知不足。 > 专栏选自&#xff1a;刷题…