详解C++赋值操作符重载

 更新时间:2020年08月15日 09:28:19   作者:Dabelv  
这篇文章主要介绍了C++赋值操作符重载的相关资料,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下

1.赋值操作符重载的原因

赋值操作符是一个使用频率最高的操作之一,通常情况下它的意义十分明确,就是将两个同类型的变量的值从一端(右端)传到另一端(左端)。但在以下两种情况下,需要对赋值操作符进行重载。
一是赋值号两边的表达式类型不一样,且无法进行类型转换。
二是需要进行深拷贝。

2. 赋值操作符重载的注意事项

赋值操作符只能通过类的成员函数的形式重载。这就说明了,如果要将用户自定义类型的值传递给基本数据类型的变量,只能通过类型转换机制,而不能利用重载来实现。

当赋值号两边的表达式不一致的时候,可能需要对赋值操作符进行重载,见下面的例子。

#include <iostream>
using namespace std;

class A
{
	int num;
public:
	A(){num=0;}
	A(int i){num=i;}
	void show(){
		cout<<num<<endl;
	}
};

int main(int argc, char* argv[])
{
	A a=5;		 //符值符号两边的数据类型不一样,这里表示创建新对象
	a.show();
	A a1;
	a1=1;    //赋值号两边的数据类型不一样,这是真正的赋值运算
	a1.show();  
}

程序的输出结果是:

5
1

在语句A a=5中,虽然用到了“=”,但它的语义是构造一个类A的对象a,它等价于语句A a(5),所以该语句与赋值无关。而语句a1=1是一个真正的赋值语句,变量a1的类型是A,而常量1的类型是int,由于可以通过类A的构造函数A(int)将类型int转换成类型A(实际上是以int为参数构造了一个类A的临时对象),然后再完成赋值操作,所以不必再对赋值操作符进行重载。

3.深拷贝情况下对赋值操作符重载

深拷贝是对赋值操作符进行重载的一个因素。那么什么是深拷贝呢?简单的说,深拷贝是在把一个类对象a拷贝到另一个对象b中去时,如果对象a中包含非悬挂指针(野指针),那么要将a的指针所指区域的内容拷贝到b的相应指针所指的区域中去。进行深拷贝时,一般对象a和b有相同的数据类型。如果在进行赋值时发生深拷贝,就一定要对赋值操作符进行重载,否则赋值运算符就会按赋值的常规语义进行(成员变量之间传递数据),而不发生深拷贝。考察如下例子。

#include <iostream>
using namespace std;

class Student
{
	char* name;
	int age;
public:
	Student()
	{
		name=new char[20];
	}

	Student(char* n, int a)
	{
		name=new char[20];
		if(name) strcpy(name,n);
		age=a;
	}

	Student(const Student& s)
	{
		name=new char[20];
		*this=s;
	}
	
	void show()
	{
		cout<<"The student's name is "<<name;
		cout<<" and of age "<<age<<endl;
	}

	~Student()
	{
		delete[] name;
	}
	
	Student& operator=(const Student &s)
	{
		if(name) strcpy(name,s.name);
		age=s.age;
		return *this;
	}
};

int main()
{
	Student s1("张三",18),s4("李四",20);
	Student s2;
	s1.show();
	s2=s4;
	s2.show();
	Student s3=s1;
	s3.show();
	return 0;
}

程序的输出结果是:

The student's name is 张三 and of age 18
The student's name is 李四 and of age 20
The student's name is 张三 and of age 18

阅读以上程序,注意如下几点。

(1)由于在类Student中,存在指针成员name,所以,当两个Student类成员之间赋值时,必须使用深拷贝。执行s2=s4;语句,就是将s4对象赋值给s2,其中将s4.name字符串的内容拷入s2.name就是对深拷贝的具体体现。

(2)类的拷贝构造函数虽然与赋值操作符并不是一回事,但通常可以在拷贝构造函数中利用赋值操作符重载,以避免对两个对象之间传递数据的重复解释。

(3)上面的程序,直接使用strcpy(name,s.name);实现两个对象的字符串成员的数据传递。这是一种简化的做法,存在很多隐患。比如如果源字符串的长度超过20个字符,此程序会出现运行时错误。解决的办法是根据原字符串的长度,重新分配目的字符串的长度,再次之前还要释放目的字符串的空间。另外,一个对象赋值给自己,也会出现问题,需要进行源对象和目的对象地址的比较,再考虑赋不赋值。

(4)由于深拷贝会涉及到内存的动态分配和释放等一些较为复杂的操作,所以程序员在编写自定义类时要尽量避免深拷贝的出现。例如,在上例中,将成员变量name定义成string name,就可以避免自己编写实现深拷贝的代码。实际的深拷贝工作是由string类来完成,而string类是C++标准库提供的,我们可放心使用。

(5)最赋值操作符进行重载时,通常将操作符函数的返回值定义为赋值左操作数类型的引用。这是为了实现对赋值表达式的求值,还有一个目的就是为了实现链式操作。

以上就是详解C++赋值操作符重载的详细内容,更多关于C++赋值操作符重载的资料请关注脚本之家其它相关文章!

相关文章

  • 在Visual Studio Code中配置C++编译环境的问题

    在Visual Studio Code中配置C++编译环境的问题

    关于Visual Studio Code对C++环境的配置方法应该有好多种,我这里用到了其中的两种,具体内容详情文中给大家详细介绍,对Visual Studio Code配置C++编译环境相关知识感兴趣的朋友一起看看吧
    2021-07-07
  • C++ 十进制转换为二进制的实例代码

    C++ 十进制转换为二进制的实例代码

    这篇文章介绍了C++ 十进制转换为二进制的实例代码,有需要的朋友可以参考一下
    2013-10-10
  • 深入探索C++中stack和queue的底层实现

    深入探索C++中stack和queue的底层实现

    这篇文章主要介绍了C++中的stack和dequeue的底层实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • C语言实现英文文本词频统计

    C语言实现英文文本词频统计

    这篇文章主要为大家详细介绍了C语言实现英文文本词频统计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • 详解C++17中nodiscard标记符的使用

    详解C++17中nodiscard标记符的使用

    在C++ 17中引入了一个标记符nodiscard,用于声明一个 “非弃值(no-discard)表达式”。这篇文章就来和大家来聊一聊nodiscard标记符的使用吧
    2023-02-02
  • C++中map容器的具体使用

    C++中map容器的具体使用

    本文主要介绍了C++中map容器的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Qt事件过滤实现点击图片的放大和缩小

    Qt事件过滤实现点击图片的放大和缩小

    这篇文章主要为大家详细介绍了Qt事件过滤实现点击图片的放大和缩小,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C语言中qsort函数的介绍与用法实例

    C语言中qsort函数的介绍与用法实例

    C语言的标准库提供了一个重要的排序函数qsort给C语言使用者使用,qsort函数将快速排序的算法封装起来,这篇文章主要给大家介绍了关于C语言中qsort函数的介绍与用法的相关资料,需要的朋友可以参考下
    2021-09-09
  • C++中对象的动态建立与释放详解及其作用介绍

    C++中对象的动态建立与释放详解及其作用介绍

    这篇文章主要介绍了C++中对象的动态建立与释放详解及其作用介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • OpenCV实现图像腐蚀

    OpenCV实现图像腐蚀

    这篇文章主要为大家详细介绍了OpenCV实现图像腐蚀,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06

最新评论