Effective C++ Item 10,11 Have assignment operators return a reference to *this Handle assignment to self in operator =

If you want to concatenate assignment like this

int x, y, z;
x = y = z = 15;

The convention is to make the assignment operators return a reference to *this.

11 Handle assignmnet to self in operator = 

You can easily assign an object to itself without knowing it

// Example 1
Foo *px, *py;
px = py;

//Example 2
a[i] = a[i];

It is dangerous to assign an object to self if your class doesn't handle this kind of opeator appropriately. Let's consider an example here:

class Bitmap{...};

class Widget {
	...
private:
	Bitmap *m_pb;
};

Widget& Widget::operator=(const Widget& rhs) {
	delete m_pb;
	m_pb = new Widget(rhs);
	return *this;
}

You will be dead if you assign an object to itself, beacause you will end up holding a pointer to a deleted object!

One way but not the best way to deal with self assignment is to write code to explicitly deal with this situation:

Widget& Widget::operator=(const Widget& rhs) {
	if(this == &rhs) {
		return *this;
	}
	
	delete m_pb;
	m_pb = new Bitmap(*rhs).m_ph;
	return *this;
}

This is not the best way because above this operator is not exception-safe. What does that mean? Imagine what if an exception is thrown when

ph = new Bitmap(*rhs.m_ph)

is been executed(for example, not enough memory), then the object will hold a pointer to a deleted object.

Luckily, making operator= safe renders it self-assignmnet-sage, too. So, the best way to accomplish that is:

Widget& Widget::operator=(const Widget& rhs) {
	Bitmap* tmp = m_pb;
	pb = new Bitmap(*rhs.m_pb);
	delete tmp;
	return *this;
}

Now if "new Bitmap" throw an exception, pb remains unchanged. Even without the identity test, this code handle assignment to self, because we make a copy of the original bitmap, point to the copy we made, and then delete the original Bitmap.

A more straightforward way to do so is to use exception-safe function swap

Widget& Widget::operator=(const Widget& ths) {
	Widget temp(ths);
	swap(temp);
	return *this;
}

  

原文地址:https://www.cnblogs.com/xinsheng/p/3572668.html