Effective C++ 条款10 令operator=返回一个reference to *this 条款11 在operator=中处理"自我赋值"

1. 为了支持形如“a=b=c”的连锁形式,最好令operator=返回一个reference to *this.

2. 如果类中含有用于指向堆内存的指针,那么赋值操作符就要注意自我赋值的问题,例如:

class A{
public:
    ...
    A& operator=(const A& tmp){
        if (ptr != tmp.ptr){
            delete ptr;
            ptr = new int(*tmp.ptr);
        }
        return *this;
    }
private:
    int* ptr;
};
View Code

以上示例虽然已经具备了"自我赋值安全性",但却不具备"异常安全性":如果"new int(*tmp.ptra)"发生异常,被赋值的ptra将指向一个已经被delete的对象,因此为了实现异常安全性,应该保证先赋值再delete,如下:

class A{
public:
        ...
    A& operator=(const A& tmp){
        int* temp = ptr;//临时储存ptr的值
        ptr = new int(*tmp.ptr);
        delete temp;
        return *this;
    }
private:
    int* ptr;
};
View Code

 以上保证了异常安全性的同时也保证了自我赋值的安全性,缺点是自我赋值虽然是安全的,但是却进行了不必要的申请内存和复制,如果自我赋值频率确实很高,可以把"证同测试“再次放回函数起始处.

3. 像上例一样在operator=内部手工排列语句的一个替代方案就是使用所谓的"copy and swap"技术,这个技术和异常安全性有密切关系(见条款29),如下:

class A{
public:
    void swap(A& rhs){
        ...
    }
    A& operator=(A tmp){//注意此处按值传递
        A temp(tmp);
        swap(temp);
    }
private:
    int* ptr;
};
View Code

这样牺牲了清晰性而且比之前的例子多了一次对象构造,但采用按值传递实际上"将'copying'动作从函数本体移至'函数参数构造阶段'",这"可令编译器有时生成更高效的代码".

4. 不只是赋值操作符,其它函数如果要操作一个以上对象,而其中有些对象可能是同一个时,也要确保函数行为的正确性.

posted @ 2015-08-22 15:08  Reasno  阅读(274)  评论(0编辑  收藏  举报