Effective C++ Item 11 在operator= 中处理“自我赋值”

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

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

示例:没有“证同测试”

#include <iostream>
#include <string>
using namespace std;

class Bitmap{
public:
	Bitmap(int s):size(s){}
	Bitmap(const Bitmap &b){
		this->size = b.size;
	}
	int getSize() const{return size;}
private:
	int size;
};

class Widget{
public:
	Widget(int size){
		pb = new Bitmap(size);
	}
	Widget &Widget::operator=(const Widget &rhs){
		delete pb;			//停止使用当前的bitmap
		pb = new Bitmap(*rhs.pb);	//使用rhs's bitmap的副本
		return *this;
	}
	Bitmap *getBitMap() const{return pb;}
private:
	Bitmap *pb;			//指针,指向一个从heap分配而得的对象
};

int main(){
	Widget w(1);
	cout << "before self assignment: " << w.getBitMap()->getSize() << endl;
	w = w;
	cout << " after self assignment: " << w.getBitMap()->getSize() << endl;
	system("pause");
}

输出:

before self assignment: 1

after self assignment: -842150451

解析:

operator=函数内的*this和rhs是同一个对象,delete销毁当前对象的bitmap,也销毁了rhs的bitmap,在函数末尾,Widget用自己持有一个指向已被删除的对象指针创建新的bitmap。所以当自我赋值后,w对象里的值变成了乱码。

纠正1:通过“证同测试”来避免自我赋值

示例:加了“证同测试”

#include <iostream>
#include <string>
using namespace std;

class Bitmap{
public:
	Bitmap(int s):size(s){}
	Bitmap(const Bitmap &b){
		this->size = b.size;
	}
	int getSize() const{return size;}
private:
	int size;
};

class Widget{
public:
	Widget(int size){
		pb = new Bitmap(size);
	}
	Widget &Widget::operator=(const Widget &rhs){
		if(this == &rhs) return *this; //这里加了“证同测试”
		delete pb;//停止使用当前的bitmap
		pb = new Bitmap(*rhs.pb);	//使用rhs's bitmap的副本
		return *this;
	}
	Bitmap *getBitMap() const{return pb;}
private:
	Bitmap *pb;			//指针,指向一个从heap分配而得的对象
};

int main(){
	Widget w(1);
	cout << "before self assignment: " << w.getBitMap()->getSize() << endl;
	w = w;
	cout << " after self assignment: " << w.getBitMap()->getSize() << endl;
	system("pause");
}

输出:

before selfassignment: 1

after self assignment: 1

纠正2:通过处理“异常安全性”来自动获得“自我赋值安全”的回报

#include <iostream>
#include <string>
using namespace std;

class Bitmap{
public:
	Bitmap(int s):size(s){}
	Bitmap(const Bitmap &b){
		this->size = b.size;
	}
	int getSize() const{return size;}
private:
	int size;
};

class Widget{
public:
	Widget(int size){
		pb = new Bitmap(size);
	}
	Widget &Widget::operator=(const Widget &rhs){
		Bitmap* pOrig = pb;         //记住原先的pb
		pb = new Bitmap(*rhs.pb);	//使用rhs's bitmap的副本
		delete pOrig;				//删除原先的pb
		return *this;
	}
	Bitmap *getBitMap() const{return pb;}
private:
	Bitmap *pb;			//指针,指向一个从heap分配而得的对象
};

int main(){
	Widget w(1);
	cout << "before self assignment: " << w.getBitMap()->getSize() << endl;
	w = w;
	cout << " after self assignment: " << w.getBitMap()->getSize() << endl;
	system("pause");
}

输出:

before selfassignment: 1

after self assignment: 1

解析:如果“newBitmap”抛出异常,pb保持原状;这段代码也能处理自我赋值。还可以把“证同测试”再次放回函数起始处,双重保险,不过有其他执行速度等的代价

纠正3:copy and swap技术

示例:

<pre name="code" class="cpp">	Widget &Widget::operator=(const Widget &rhs){
		Widget temp(rhs);
		swap(temp);
		return *this;
	}
	或
	Widget &Widget::operator=( Widget rhs){ //将”copying动作”从函数本体移到“函数参数构造阶段”
		swap(rhs);
		return *this;
	}

Effective C++ Item 11 在operator= 中处理“自我赋值”

时间: 2024-10-04 21:59:33

Effective C++ Item 11 在operator= 中处理“自我赋值”的相关文章

effective c++ Item 11 在operator=中处理自我赋值

1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: 1 class Widget { ... };2 3 Widget w;4 5 ...6 7 w = w; // assignment to self. 这看上去是愚蠢的,但这是合法的,所以请放心,客户端是可以这么做的.此外,自身赋值也并不总是很容易的能够被辨别出来.举个例子: 1 a[i] = a[j]; // potential assignment to self 上面的代码在i和j相等的情况下就是自我赋值,同样的,

读书笔记 effective c++ Item 11 在operator=中处理自我赋值

1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: 1 class Widget { ... }; 2 3 Widget w; 4 5 ... 6 7 w = w; // assignment to self. 这看上去是愚蠢的,但这是合法的,所以请放心,客户端是可以这么做的.此外,自身赋值也并不总是很容易的能够被辨别出来.举个例子: 1 a[i] = a[j]; // potential assignment to self 上面的代码在i和j相等的情况下就是自我赋值,同

Effective C++ 条款11,12 在operator= 中处理&ldquo;自我赋值&rdquo; || 复制对象时不要忘记每一个成分

1.潜在的自我赋值     a[i] = a[j];     *px = *py; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象,当其中一个对象被删,另一个也被删,这会造成不想要的结果. 该怎么办? 比如:   widget& widget:: operator+ (const widget& rhs) {    delete pd;    pd = new bitmap(*rhs.pb);    return *thi

Effective C++_笔记_条款11_在operator=中处理“自我赋值”

(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为什么会出现自我赋值呢?不明显的自我赋值,是“别名”带来的结果:所谓“别名”就是“有一个以上的方法指涉对象”.一般而言如果某段代码操作pointers或references而它们被用来“指向多个相同类型的对象”,就需要考虑这些对象是否为同一个.实际上两个对象来自同一个继承体系,它们甚至不需要声明为相同类型就可能造成“别名”.因为一个base class的refe

条款11:在operator = 中处理&quot;自我赋值&quot;

条款11:在operator = 中处理"自我赋值" 1.潜在自我赋值 int i = 5; int *x = &i; int *y = &i; *x = *y; 继承类的 class Base{}; class Derived: public Base {}; void DoSomeThing(const Base& base, const Derived &derived) { base = derived; } Derived d; Base *b

用3种方法在 operator= 中处理“自我赋值”

假设你建立一个class 用来保存一个指针指向一块动态分配的位图. 1 class Bitmap {......}; 2 class Widget{ 3 ... 4 private: 5 Bitmap* pb ; 6 }; 1 Widget& Widget::operator= (const Widget& rhs) 2 { 3 delete pb; 4 pb = new Bitmap(*rhs.pb); 5 return *this; 6 } 上面是一份不安全的 operator= 实现

NO.10: 在operator=中处理 &quot;自我赋值&quot;

1.确保当对象自我赋值时operator=有良好的行为,其中的技术包括 "来源对象" 和 "目标对象" 的地址,精心周到的语句顺序,以及" copy and swap " 技术 2.确定任何函数执行操作一个以上对象时,而其中多个对象是同一个对象时,其行为任然正确 1 #include <iostream> 2 3 4 //1.0 5 class CopySwap1_0 6 { 7 private: 8 int *value; 9 pu

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

**如果赋值操作=左右值相等,即自我赋值,传统做法: 证同策略:** 为防止new异常,需要在new之前不删除原先的引用: swap技术的运用: 当传递的是值不是引用时同样可用swap: 注意:

Effective C++ Item 10 令operator= 返回一个reference to *this

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:令赋值(assignment)操作符返回一个reference to *this --> 这样可以实现级联赋值 示例: #include <iostream> #include <string> using namespace std; class Widget{ public: Widget(int v):value(v){} Widget& opera