关于“operator=”

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 17:24   1036   0

一、中心思想

1、令赋值操作符返回一个*this的引用;

2、确保“自我赋值”时,operator=有良好行为(特别是异常安全)。。包括比较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及copy-and-swap;

3、拷贝函数(拷贝构造函数和拷贝操作符)应该确保复制“对象内的所有成员变量”以及“所有基类成分”;

4、不要师徒用某个拷贝函数实现另外一个拷贝函数。。。。应该将共同机能的代码放进第三个函数,并由两个拷贝函数共同调用

二、内容简介

1、如何处理自我赋值,特别是行为像指针的类

(1)几种潜在的自我赋值

1)a[i] = a[j];//i=j的时候,就是自我赋值

2)*px = *py;//当两个指针指向同一个内容时

3)两个对象来自同一个继承体系,不需要声明为相同类型就可能造成别名。

e.g

class Base{......};

class Derived: publilc Base {......};

void dosomething(const Base& rb, Derived* pd);//rb和*pd有可能是同一个对象

(2)几种“自我赋值”的处理方式

e.g

考虑如下的类

class Bitmap {...};

class Widget{...

......

private:

Bitmap* pb;

};

1)不安全的实现版本

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

{

delete pb;

pb = new Bitmap(*rhs.pb);

return *this;

}

note:

1、赋值符号右边的对象保持不变;

2、若rhs与*this是同一个对象,那么执行后的this指针可能会指向一个没有内容的对象,即已经被删除的对象。


2)加上证同测试的不安全版本(异常安全问题)

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

{

if(this == &rhs) return *this; //证同测试

delete pb;

pb = new Bitmap(*rhs.pb);

return *this;

}

note:

此代码可以避免1)中2的问题。。。

但是,若new Bitmap 出现了问题(分配时内存不足或因为Bitmap的拷贝构造函数抛出异常),不同对象进行赋值时,就会出现问题,导致最终this指针会指向一个被删除的对象。


3)安全版本

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

{

Bitmap* cpb = pb; //记住原先的pb;

pb = new Bitmep(*rhs.pb);

delete cpb;

return *this;

}

note:

即使此时new Bitmap 发生异常抛出,原来的pb仍然可以保持原样。。。

3)两种使用swap()函数的较佳版本

class Widget{

......

void swap(Widget& rhs); //定义自己的swap函数;

......

};

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

{

Widget temp(rhs);

swap(temp);

return *this;

}

或者:

Widget& Widget::operator=( Widget rhs)

{

swap(rhs);

return *this;

}

note:

后者和前者相比:

1、优点:

将复制动作从“函数本体”移至“函数参数构造阶段”可以提高代码的效率;

2、缺点:

可读性没有那么强。


2、拷贝对象时,不要忘记每一个成分(特别是继承体系中)

(1)拷贝函数包括:拷贝构造函数、拷贝操作符函数。。。。对比两者:

1)拷贝构造函数:

进行直接初始化新构造的一个对象;

2)拷贝操作符函数:

只作用于已经初始化的对象,进行赋值操作。符号右边的对象保持不变。。

(2)继承体系中的拷贝操作

note:由于成员变量通常是private, 所以派生类常常无法直接调用,所以通常调用基类的相应拷贝函数。

e.g

PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)

Customer(rhs), priority(rhs. priority) //调用基类的拷贝函数

{

......

}

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

{

. .....

Customer::operator=(rhs); //调用基类成分进行赋值

priority = rhs.priority;

return *this;

}






分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP