赋值运算符“=”编程
类为具有指针存储char字符串的一个自定义CMyStr类。
CMyString 类定义
#include <string.h>
class CMyString
{
private:
char* m_pData;
public:
CMyString(char* pData = nullptr);
CMyString(const CMyString& MyStr);
~CMyString(void);
CMyString& operator=(const CMyString& Str);
};
CMyString::CMyString(char* pData)
{
if (pData == nullptr) return;
size_t len = strlen(pData) + 1;
m_pData = new char[len];//记得要加1,放置'\0'
strcpy_s(m_pData, len, pData);
}
inline CMyString::CMyString(const CMyString & MyStr)
{
size_t len = strlen(MyStr.m_pData) + 1;
m_pData = new char[strlen(MyStr.m_pData)+1];//记得要加1,放置'\0'
strcpy_s(m_pData, len, MyStr.m_pData);
}
inline CMyString::~CMyString(void)
{
delete[]m_pData;
}
第一种实现
四个关键点
- 返回值为本身的引用,便于连续等于,如 a=b=c,如果返回值不是引用,则无法连等。
- 形参为const引用,避免因为值传递调用复制构造函数
- 判断传入的对象是否为自身,如果是则跳过
if (&Str == this)
- 如果存储的数据为指针,则要将已有空间析构
代码
inline CMyString & CMyString::operator=(const CMyString & Str)
{
if (&Str == this) //判断是否是自身
return *this;
delete[]m_pData;
m_pData = nullptr;
m_pData = new char[strlen(Str.m_pData)+1];//记得要加1,放置'\0'
strcpy(m_pData, Str.m_pData);
return *this;
}
第二种实现
考虑更好的内存稳定型和异常处理
- 使用复制构造函数
- 以传入的形参为基础,调用复制构造函数创建临时对象
- 将临时对象与当前对象交换指针
- 离开函数时,临时对象析构,自动销毁原对象的空间
代码
利用临时对象和 拷贝构造函数,临时对象离开函数后自动析构
inline CMyString & CMyString::operator=(const CMyString & Str)
{
if (&Str != this)//判断是否是自身
{
CMyString tmpStr(Str);
char* pTmp = tmpStr.m_pData;
tmpStr.m_pData = m_pData;
m_pData = pTmp;
cout << "execute copy operator" << endl;
}
return *this;
}
拷贝构造函数和赋值运算符的区别
拷贝构造函数:使用传入对象的值生成一个新的对象。
赋值运算符:将对象的值赋值给一个已经存在的实例
调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生,如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符。
调用拷贝构造函数主要有以下场景:
1. 对象作为函数的参数,以值传递的方式传给函数。
2. 对象作为函数的返回值,以值的方式从函数返回。
3. 使用一个对象给另一个对象初始化。
!!需注意**等于号=**并不等于一定使用赋值运算符:
Person p;
Person p1 = p; // 此时虽然是等于号,但是因为p1是新对象,所以仍然是调用的 拷贝构造函数
测试
#include <iostream>
using namespace std;
#include "MyString.h"
void test()
{
CMyString s1("my string hh!");
CMyString s2(s1);//复制构造函数
CMyString s3;
s3 = s2; //赋值运算符
s3 = s3; //函数内跳过赋值,因为是本身
CMyString s4("New things!");
CMyString s5 = s3 = s4; //复制构造函数 + 赋值运算符
CMyString s6 = s5; //复制构造函数
}
int main()
{
test();
system("pause");
return 0;
}
CMyString s5 = s3 = s4; //复制构造函数 + 赋值运算符
CMyString s6 = s5; //复制构造函数
}
int main()
{
test();
扫描二维码关注公众号,回复:
10650787 查看本文章
system("pause");
return 0;
}