C+笔记六十五:重载等号操作符实现深拷贝

一、问题引入

【笔记四十九:C++中的浅拷贝】有程序,当时我们编译可以通过,但是运行会出错,因为对象obj2=obj1进行赋值时,采用浅拷贝,导致对象析构时会对同一块内存空间析构两次。也就是说等号操作符“=”,默认是进行浅拷贝,我们需要对等号操作符进行重载,使其能够进行深拷贝。

原浅拷贝程序

#define_CRT_SECURE_NO_WARNINGS

#include

usingnamespacestd;

className

{

public:

//构造函数

Name(constchar*myp)

{

len=strlen(myp);//字符串的长度,不含'0'

p=(char*)malloc(len+1);//申请内存,要包含

strcpy (p,myp);//字符串放到类中

}

//析构函数

~Name()

{

if(p!=NULL)

{

free(p);

p=NULL;

len=0;

}

}

protected:

private:

char*p;//类里面含有指针,有可能出现深拷贝和浅拷贝的问题

intlen;

};

voidobjplay()

{

Name obj1("abcdefg");

Name obj2=obj1;//调用obj2的拷贝构造函数

//没写拷贝构造函数,使用C++编译器默认的拷贝构造函数

//C++编译器提供的拷贝构造函数是一个浅拷贝

//就是指针变量赋值了,但是指针变量所指向的内存空间没有被拷贝过去

//两个对象的指针属性指向同一块内存空间

}

intmain()

{

objplay();

system("pause");

return0;

}

二、重载等号操作符

按照步骤通过成员函数重载等号操作符:

(1)要承认操作符重载是一个函数,写出函数名称

operator=

(2)根据操作数,写出函数参数

obj2=obj1,操作数由两个,所以函数调用形式为:obj2.operator=(obj1)

(3)根据业务,完善函数返回值(看函数返回引用、元素还是指针),及实现函数业务

void operator=(Name &c1)

完成程序

#include

usingnamespacestd;

className

{

public:

//带参数构造函数

Name(constchar*myp)

{

len=strlen(myp);//字符串的长度,不含'0'

p=newchar[len+1];//申请内存,要包含

strcpy (p,myp);//字符串放到类中

}

//手工编写拷贝构造函数,使用深拷贝

Name(constName &obj)

{

len=obj.len;

p=newchar[len+1];

strcpy(p,obj.p);

}

//析构函数

~Name()

{

if(this->p!=NULL)

{

delete(this->p);

this->p=NULL;

len=0;

}

}

//等号操作符重载函数

voidoperator=(Name &obj1)

{

//先释放旧的内存

if(this->p!= NULL)

{

delete[]p;

len=0;

}

//根据obj1分配内存大小

this->len=obj1.len;

this->p=newchar[len+1];

//把obj1赋值

strcpy(p,obj1.p);

}

intgetLen()

{

returnlen;

}

protected:

private:

char*p;//类里面含有指针,有可能出现深拷贝和浅拷贝的问题

intlen;

};

voidobjplay()

{

Name obj1("abcdefg");//调用obj1的带参构造函数

Name obj2("abc");//调用obj2的带参构造函数

//调用等号操作符重载函数

obj2=obj1;

cout

//调用拷贝构造函数

//没有调用等号操作符重载函数

Name obj3=obj1;

cout

}

intmain()

{

objplay();

cout

system("pause");

return0;

}

我们单步调试程序,发现以下语句会调用等号操作符重载函数:

//调用等号操作符重载函数

obj2=obj1;

cout

但是,下面的语句会依旧调用考诶构造函数,不会调用等号操作符重载函数:

//调用拷贝构造函数

//没有调用等号操作符重载函数

Name obj3=obj1;

cout

具体原因目前我也不知道,知道了再写!

三、重载等号操作符支持链式编程

上面的程序中,如果我们再定义一个对象,然后obj2=obj1=obj3;我们发现编译错误,void类型不能做右值。这一个跟我们重载

等号操作符的实行顺序是从右往左的,也就是先执行obj1=obj3,然后函数返回void型,然后继续执行就是 obj2 = void,所以就会报错。

obj2=obj1=obj3执行时第一步需要将obj3赋给obj1,第二步obj1赋给obj2,所以我们在执行第一步时应该返回一个obj1就可以了,也就是返回一个Name类的对象,返回obj1对象本身,因此我们可以返回一个引用:Name &operator=(Name &obj1)

#include

usingnamespacestd;

className

{

public:

//带参数构造函数

Name(constchar*myp)

{

len=strlen(myp);//字符串的长度,不含'0'

p=newchar[len+1];//申请内存,要包含

strcpy (p,myp);//字符串放到类中

}

//析构函数

~Name()

{

if(this->p!=NULL)

{

delete(this->p);

this->p=NULL;

len=0;

}

}

//等号操作符重载函数

Name &operator=(Name &obj1)

{

//先释放旧的内存

if(this->p!= NULL)

{

delete[]p;

len=0;

}

//根据obj1分配内存大小

this->len=obj1.len;

this->p=newchar[len+1];

//把obj1赋值

strcpy(p,obj1.p);

return*this;

}

intgetLen()

{

returnlen;

}

protected:

private:

char*p;//类里面含有指针,有可能出现深拷贝和浅拷贝的问题

intlen;

};

voidobjplay()

{

Name obj1("abcdefg");//调用obj1的带参构造函数

Name obj2("abc");//调用obj2的带参构造函数

Name obj3("ab");

//调用等号操作符重载函数

obj2=obj1=obj3;

cout

}

intmain()

{

objplay();

cout

system("pause");

return0;

}

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180520A19QVK00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券