这里所说的特种成员函数包括C++98已有的默认拷贝函数、析构函数、复制构造函数、复制赋值运算符以及C++11新增的移动构造函数以及移动赋值运算符。这些特种成员函数在特定场合,编译器都可以自动为其生成,且访问权限都是public的,inline类型的。

以下几点是特种成员函数生成的特点:

  1. 仅当一个类没有声明任何构造函数时,编译器才会自动生成默认构造函数。

  2. 当基类的析构函数是虚函数时,编译器为子类生成的默认析构函数也才会是虚函数,且析构函数默认为noexcept的。

  3. 默认的移动构造函数以及移动赋值运算符会对非静态成员变量也尝试进行移动操作,如果非静态成员变量无法移动,将执行赋值操作。

  4. 复制构造函数及复制赋值运算符是相互独立的,如果人工生成了其中一个,不会阻止编译器为另外一个生成默认函数,但为了更好的兼容性,我们应该都人为生成一下。

  5. 移动构造函数以及移动赋值运算符却是关联的,如果人工生成了其中一个,将阻止编译器为另外一个生成默认函数。因为编译器认为既然需要人为的自定义一个移动操作,说明默认移动操作不满足要求,为了避免编译器生成的默认函数与你设计不服,编译器将直接不生成。

  6. 一旦人为声明了复制构造函数或复制赋值运算符,编译器将被阻止生成默认的移动构造函数以及移动赋值运算符。因为编译器认为既然默认复制操作不满足条件,则移动操作也一定不满足条件。反之亦然,一旦人为声明了移动构造函数或移动赋值运算符,编译器将被阻止生成默认的复制构造函数及复制赋值运算符。

  7. 一旦声明了析构函数,编译器将被阻止生成移动操作,所有需要移动操作的地方,将全部被换为复制操作。

  8. 对特种成员函数使用=default来显示定义,编译器将为其生成默认函数。所以,如果确认默认特种函数满足要求,那我们最好对所有特种成员函数执行该操作,以避免编译报错或移动被复制替换等问题发生

  9. 成员函数模板在任何情况下都不会抑制特种成员函数的生成

以下几条虽然现有C++11对其并未做约束,但是为了更好的向上迭代性,我们应该满足以下要求:

  1. 如果我们人为声明了复制构造函数、复制赋值运算符及移动构造函数、移动赋值运算符的其中一个,那我们就要将其余三个都人为声明一下,不能依赖于编译器为我们默认生成。

  2. 如果我们声明了析构函数,则也需要将复制构造函数及复制赋值运算符也声明出来。因为编译器认为析构函数既然是需要人为声明,那就说明存在内存管理,默认的复制构造函数及复制赋值运算符可能不满足要求。

  3. 如果我们声明了复制操作,就要将移动操作也声明出来,因为此时编译器将不会为我们生成默认移动操作,所有使用移动操作的地方将被复制替代。