《Effective C++》 读书笔记之二 构造/析构/赋值运算

条款10:令赋值(assignment)操作符返回一个reference to *this。

例子:

Widget& operator=(const Widget& rhs)
{
    ...
    return *this;//返回*this
}

2016-11-03 09:36:00


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

例子:

class Widget{
    ...
    void swap(Widget& rhs);//交换*this与rhs的数据
    ...
};

//第一种合理安全的写法
Widget& Widget::operator=(const Widget& rhs)
{
    BitMap * pOrg = pb;        //记住原先的pb
    pb = new BitMap(*rhs.pb);    //令pb指向*pb的一个复件(副本)
    delete pOrg;                //删除原先的pb
    return *this;
}
//第二种合理安全的写法
Widget& Widget::operator=(const Widget& rhs)
{
    Widget temp(rhs);
    swap(temp);
    return *this;
}

重点:

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

  2. 确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。

2016-11-03 10:23:50


条款12:复制对象时勿忘其每一个成分。Copy all parts of an object.

例子:

void logCall(const std::string& funcName);
class Customer{
public:
    Customer(const Customer& rhs);.
    Customer& operator=(const Customer& rhs);
private:
    std::string name;
};
Customer::Customer(const Customer& rhs)
    :name(rhs.name) //复制所有成员,防止局部拷贝(partial copy )
{
    logCall("Customer copy constructor");
}
Customer& Customer::operator=(const Customer& rhs)
{
    logCall("Customer copy assignment operator");
    name = rhs.name;
    return *this;
}
class PriorityCustmer: public Custmer //一个derived class
{
public:
    PriorityCustomer(const PriorityCustomer& rhs);
    PriorityCustomer& operator=(const PriorityCustomer& rhs);
private:
    int priority
};
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
    :Customer(rhs),//调用base class的copy构造函数,如果不调用,会调用Customer的default构造函数
    priority(rhs.priority)
{
    logCall("PriorityCustomer copy constructor");
}
PriorityCustomer&
PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
    logCall("PriorityCustomer copy assignment operator");
    Customer::operator=(rhs);//对base class成分进行赋值动作
    priority=rhs.priority;
    return *this;
}

重点:

  1. Copying函数应该确保复制“对象内的所有成员变量”及“所有base class成分”。

  2. 不要尝试以某个copying函数实现另一个copying函数。应该将共同机能放进第三个函数中,比如init(),并由两个copying函数共同调用。

2016-11-03 11:20:20