码迷,mamicode.com
首页 > 编程语言 > 详细

effective C++ 读书笔记 条款11

时间:2014-11-14 12:42:15      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:style   io   color   os   使用   sp   on   cti   bs   

条款11: 在operator= 中处理“自我赋值”

 

在实现operator=时考虑自我赋值是必要的就像 x=y ,我们不知道变量x与y代表的值是否为同一个值(把x和y说成是一个指针更恰当一点)。如下

 

第一版:

#include <iostream>

using namespace std;

class bitmap
{
public:
	bitmap()
	{
		cout<<"调用bitmap()无参构造函数"<<endl;
	}
	bitmap(const bitmap& bt)
	{
		this->i = bt.i;
		cout<<"调用bitmap()拷贝构造函数"<<endl;
	}
	~bitmap()
	{
	}
private:
	int i;
};
class Widget
{
public:
	Widget()
	{
		pb = new bitmap();
	}
	Widget(const Widget& wd)
	{
		this->pb = wd.pb;
	}
public:
	Widget& operator=(const Widget& rhs);
private:
	bitmap* pb; //定义一个从heap分配而得的对象
};

//第一版赋值函数:
Widget& Widget::operator=(const Widget& rhs)
{
	delete pb;
	pb = new bitmap(*rhs.pb);
	return *this;
}
//这一版函数的pb在使用前清理掉之前的pb指向,再接受一个new出来的新对象,看着很顺理成章,但是
//当this与函数参数rhs相等的时候,pb = new bitmap(*rhs.pb);因为我们已经把*rhs.pb delete掉了。

int main()
{

	Widget w1;
	Widget w2;
	w1 = w2;
	return 0;
}
/*
调用bitmap()无参构造函数
调用bitmap()无参构造函数
调用bitmap()拷贝构造函数
Press any key to continue
*/


第二版:

//第二版赋值函数:
Widget& Widget::operator=(const Widget& rhs)
{
	if (this == &rhs)
	{
		return *this;
	}

	delete pb;
	pb = new bitmap(*rhs.pb);
	return *this;
}
//这个版本行的通,赋值函数基本上是可以接受的,但是不见得是安全的,因为当new产生异常时pb依然是一个
//不确定的指针。


第三版:

//第三版赋值函数:
Widget& Widget::operator=(const Widget& rhs)
{
	bitmap *pOrig = pb;
	pb = new bitmap(*rhs.pb);
	delete pOrig;
	return *this;
}
//第三版函数在开始的时候用pOrig记录了pb,当new没有异常时我们再把pb原来的指向空间释放掉
//从而提高了安全性。这种方法也同样能够处理自我赋值,假如这里rhs=*this;我们先对原来的
//bitmap做了一份备份,删除原bitmap后,指向了我们的那一份备份,或许这种处理自我赋值的方法
//不是很好,但是行的通,在保证安全性的情况下采用这种办法很不错。


 

第四版:

#include <iostream>

using namespace std;

class bitmap
{
public:
	bitmap()
	{
		cout<<"调用bitmap()无参构造函数"<<endl;
	}
	bitmap(const bitmap& bt)
	{
		this->i = bt.i;
		cout<<"调用bitmap()拷贝构造函数"<<endl;
	}
	~bitmap()
	{
	}
private:
	int i;
};
class Widget
{
public:
	Widget()
	{
		cout<<"调用Widget()无参构造函数"<<endl;
		pb = new bitmap();
	}
	Widget(const Widget& wd)
	{
		cout<<"调用Widget()拷贝参构造函数"<<endl;
		this->pb = wd.pb;
	}
	void my_swap(Widget& rhs);
public:
	Widget& operator=(const Widget& rhs);
private:
	bitmap* pb; //定义一个从heap分配而得的对象
};

//第四版赋值函数:

void Widget::my_swap( Widget& rhs)
{
	pb = rhs.pb;
}

Widget& Widget::operator=(const Widget& rhs)
{
	Widget temp(rhs);//防止改变rhs
	my_swap(temp);
	return*this;
}
//第四版赋值函数利用的是copy and swap技术,这个技术在条款29当中
//有详细说明,还没认真看,这里就不解释了。

//第四版也可以这样用:
Widget& Widget::operator=(Widget rhs)
{
	my_swap(rhs); //其实本质上是一样的,因为传递的参数是值传递,所以这里传递的是rhs的一个副本,相当于Widget temp(rhs);主要就是防止rhs被改变;
	return*this;
}


int main()
{
	
	Widget w1;
	Widget w2;
	w1 = w2;
	return 0;
}
/*
调用Widget()无参构造函数
调用bitmap()无参构造函数
调用Widget()无参构造函数
调用bitmap()无参构造函数
调用Widget()拷贝参构造函数
Press any key to continue
*/


总结:

1:确保当对象自我赋值时 operator= 有良好行为,其中技术包括比较“原来对象”和“目标对象”的地址。、精心周到的语句顺序,以及copy and swap

2:确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。

 

effective C++ 读书笔记 条款11

标签:style   io   color   os   使用   sp   on   cti   bs   

原文地址:http://blog.csdn.net/djb100316878/article/details/41114977

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!