剑指offer,面试题一:赋值运算符函数

来源:互联网 发布:jsp中如何引用js文件 编辑:程序博客网 时间:2024/05/22 12:58

赋值运算符“=”的重载

  对任一类X,如果没有用户自定义的赋值运算符函数,那么系统将自动地为其生成一个默认的赋值运算符函数,但是在某些特殊情况下,如类中有指针类型时,使用默认赋值运算符函数会产生错误,也就是所谓的指针悬挂问题(对同一内存空间的两次释放)。

  我们用深层复制解决指针悬挂问题,必须显式定义一个自己的赋值运算符重载函数,使之不但复制数据成员,而且为对象分配了各自的内存空间,这就是所谓的深层复制。

  我们要注意以下几点:

  (a)返回值类型声明为该类型的引用,只有返回引用,才可以连续赋值;

  (b)传入参数声明为常量引用,如果传入的参数是实例而不是引用,那么从形参到实参会调用一次构造函数,把参数声明为引用,可以避免这类消耗,提高代码质量;

  (c)记得释放实例自身已有的内存,如果我们忘记在分配新内存之前释放已有的内存,这样会造成内存泄露;

  (d)判断传入参数是否和当前实例的值相同,如果相同,则不进行赋值操作。

   代码示例如下:

class CMyString{public:CMyString(char* pData);~CMyString();CMyString& operator = (const CMyString &str);void Print();void Fu_Zhi1(CMyString &p1, CMyString &p2);void Fu_Zhi2(CMyString &p1, CMyString &p2);void Fu_Zhi3(CMyString &p1, CMyString &p2, CMyString &p3);public:char *my_pData;};#include "StdAfx.h"#include "MyString.h"#include<iostream>#include<string>using namespace std;CMyString::CMyString(char* pData){if(pData == NULL){pData = new char[1];my_pData = '\0';}else {cout<<"Constructor called"<<endl;int length = strlen(pData);my_pData = new char[length+1];strcpy(my_pData, pData);}}CMyString::~CMyString(){cout<<"Destructor called.---"<<my_pData<<endl;delete my_pData;}CMyString& CMyString::operator = (const CMyString &str)//定义赋值运算符重载函数{if(this == &str)return *this;delete my_pData;my_pData = new char[strlen(str.my_pData) + 1];strcpy(my_pData, str.my_pData);return *this;}void CMyString::Print(){cout<<my_pData<<endl;}void CMyString::Fu_Zhi1(CMyString &p1, CMyString &p2)//引用为形参,改变传入实参的值,普通赋值{p2 = p1;p2.Print();}void CMyString::Fu_Zhi2(CMyString &p1, CMyString &p2)//自身赋值{p1 = p2;p1.Print();}void CMyString::Fu_Zhi3(CMyString &p1, CMyString &p2, CMyString &p3)//连续赋值{p3 = p2 = p1;p2.Print();p3.Print();}int main(){CMyString s1("book");CMyString s2("jeep");CMyString s3("tree");s1.Fu_Zhi1(s1,s2);s1.Fu_Zhi2(s1,s1);s1.Fu_Zhi3(s3,s2,s2);system("pause");return 0;}


0 0