10 August 2022

C++ 核心指南目录

C.22: Make default operations consistent

理由

默认操作函数,是一组概念上匹配的操作函数集。其语义是相关联的。如果拷贝/移动构造函数、拷贝/移动赋值函数的逻辑行为不一致,会让用户很抓狂。如果构造和析构函数对资源的操作方式不一致,用户也会觉得很惊讶。如果拷贝和移动操作、构造和析构操作不对应,用户也会很惊讶。

例子

class Silly {   // BAD: Inconsistent copy operations
    class Impl {
        // ...
    };
    shared_ptr<Impl> p;
public:
    Silly(const Silly& a) : p(make_shared<Impl>()) { *p = *a.p; }
    // deep copy
    Silly& operator=(const Silly& a) { p = a.p; }
    // shallow copy
    // ...
};

以上,构造函数和拷贝构造函数的操作不一致,一个是深复制,一个是浅复制。这会导致误解,产生 bug 。

强化

  • (复杂)拷贝/移动构造函数与对应的拷贝/移动赋值函数要在成员变量的同一层级进行读写操作。
  • (复杂)任何在拷贝/移动构造函数中改写的成员变量要在其他构造函数中初始化。
  • (复杂)如果拷贝/移动构造函数对一个成员变量进行深复制,析构函数也应该修改此成员变量。
  • (复杂)如果析构函数要修改一个成员变量,这个变量必须是在其他拷贝/移动构造或赋值函数中修改过。