关于工作和读书的笔记
[原创文章欢迎转载,但请保留作者信息]Justin 于 2009-11-12
第十项所言无他,就是要记得定义拷贝运算符时要返回对象自身的引用(*this)。原因很简单,你会有连着用=号的时候(a=b=c),如果不返回对象的引用这一串赋值式子就无法传递下去。
Item11说的也是拷贝运算符,不过侧重点在使用=号对自身赋值的特殊情况(a=a)。再继续下去之前Scott先是举了个很傻的例子:一个赋值函数
这样的一个傻傻赋值函数有两个问题: 1. 在自赋值的时候是要出事的。(在自赋值的时候:pb被释放之后,紧接着就又被当作右值来构造新的对象……) 2. 在发生异常的时候也是要出事的。(设想如果在new的过程中出错然后抛出异常,结果就是我们的pb成了野指针:它指向一个已经delete了的内存空间,你无法再次delete它,也不能读,因为你不知道你读到的是什么@#¥%)
于是就有了以下应付自赋值的策略:
Widget&Widget::operator=(Widget rhs) // rhs is a copy of the object{ // passed in — note pass by val swap(rhs); // swap *this's data with // the copy's return *this;}
最后要炒的是第12项,讲的也还是拷贝运算符:如何保证在赋值/拷贝的时候能够将所有的成员完整拷贝过去?对于简单的数据成员,编译器自动生成的拷贝函数可以保证一个不漏都帮你拷贝;如果是比较复杂的成员(比如说指向一片内存空间的指针),编译器就没有足够的智商把这些成员拷贝到另外一个对象中去了。
自己动手丰衣足食,还是要自己写。然而人写的东西终究还是会有各种问题,比如说:
第一个问题没人能帮忙,只能靠自己小心。第二个问题,方法比较直接了:在子类的拷贝函数中调用父类的拷贝函数(老爸,劳烦您也拷贝一下吧~~),代码:
最后的最后,通常来说在拷贝函数和拷贝构造函数中的实现大多相同,大师就很贴心的提醒:不要在拷贝函数中调用拷贝构造函数或者反之。如果真的需要避免代码的重复,大可定义一个私有的函数来负责前面两者相同的部分。
Copyright @ Justin.H Powered by: .Text and ASP.NET Theme by: .NET Monster