拷贝构造函数 和 赋值运算符函数

一、拷贝构造函数

C++ 中经常会使用一个变量初始化另一个变量,如

int x = 1;

int y = x;

我们希望这样的操作也能作用于自定义类类型,如

Point pt1(1, 2);

Point pt2 = pt1;

这两组操作是不是一致的呢?第一组好说,而第二组只是将类型换成了 Point 类型,执行 Point pt2 = pt1; 语句时, pt1 对象已经存在,而 pt2 对象还不存在,所以也是这句创建了 pt2 对象,既然涉及 到对象的创建,就必然需要调用构造函数,而这里会调用的就是复制构造函数,又称为拷贝构造函数。 当我们进行测试时,会发现我们不需要显式给出拷贝构造函数,就可以执行第二组测试。这是因为如果 类中没有显式定义拷贝构造函数时,编译器会自动提供一个缺省的拷贝构造函数。其原型是: 

类名::类名(const 类名&);

那缺省(默认)的拷贝构造函数是如何实现的呢?很简单,我们来实现一下 Point 类的拷贝构造函数:

Point::Point(const Point & rhs)

: _ix(rhs._ix)

, _iy(rhs._iy)

{} 

 从上面的定义来看, pc1 与 pc2 对象的数据成员 _brand 都会指向同一个堆空间的字符串,这种只拷贝 指针的地址的方式,我们称为浅拷贝。当两个对象被销毁时,就会造成 double free 的问题。显然, 缺省拷贝构造函数不再满足需求,此时需要显式定义拷贝构造函数:

Computer::Computer(const Computer & rhs)

: _brand(new char[strlen(rhs._brand) + 1]())

, _price(rhs._price)

{    

strcpy(_brand, rhs._brand);

}

这种拷贝指针所指空间内容的方式,我们称为深拷贝。因为两个对象都拥有各自的独立堆空间字符串, 一个对象销毁时就不会影响另一个对象。

拷贝构造函数的调用时机:

  1. 当把一个已经存在的对象赋值给另一个新对象时,会调用拷贝构造函数。
  2.  当实参和形参都是对象,进行实参与形参的结合时,会调用拷贝构造函数。
  3.  当函数的返回值是对象,函数调用完成返回时,会调用拷贝构造函数。 

二 、赋值运算符函数

 赋值运算是一种很常见的运算,比如:

int x = 1, y = 2;

x = y;

同样地, 我们也希望该操作能作用于自定义类类型,比如:

Point pt1(1, 2), pt2(3, 4);

pt1 = pt2;//赋值操作 

在执行 pt1 = pt2; 该语句时, pt1 与 pt2 都存在,所以不存在对象的构造,这要与 Point pt2 = pt1; 语句区分开,这是不同的。

在这里,当 = 作用于对象时,其实是把它当成一个函数来看待的。在执行 pt1 = pt2; 该语句时,需要 调用的是赋值运算符函数。其形式如下: 

返回类型 类名::operator=(参数列表)

{  

 //...

}

当我们进行测试时,会发现我们不需要显式给出赋值运算符函数,就可以执行测试。这是因为如果类中 没有显式定义赋值运算符函数时,编译器会自动提供一个缺省的赋值运算符函数。对于 Point 类而言, 其实现如下 

Point & Point::operator=(const Point & rhs)

{  

 _ix = rhs._ix;

 _iy = rhs._iy;

}

然而,当我们对Computer对象也执行赋值操作时,又会发生什么呢?先看 Computer 类的赋值运算符 函数的实现:

Computer & Computer::operator=(const Computer & rhs)

{

_brand = rhs._brand;  

 _price = rhs._price;    

return *this;

很显然,这里默认情况下依然会采用浅拷贝的方式拷贝字符串。当两个对象被销毁时,同样会造成 double free 的问题,因此缺省赋值运算符函数不再满足需求,此时需要显式定义赋值运算符函数:

Computer & Computer::operator=(const Computer & rhs)

{  

     if(this != &rhs) {      

        delete [] _brand;  

       _brand = new char[strlen(rhs._brand) + 1]();

       strcpy(_brand, rhs._brand);      

       _price = rhs._price;

     }  

 return *this;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值