17理解特种成员函数的生成机制:
这里所说的特种成员函数包括C++98已有的默认拷贝函数、析构函数、复制构造函数、复制赋值运算符以及C++11新增的移动构造函数以及移动赋值运算符。这些特种成员函数在特定场合,编译器都可以自动为其生成,且访问权限都是public的,inline类型、非虚的。
以下几点是特种成员函数生成的特点:
- 仅当一个类没有声明任何构造函数时,编译器才会自动生成默认构造函数。
- 只有当基类的析构函数是虚函数时,编译器为子类生成的默认析构函数也才会是虚函数,且析构函数默认为noexcept的。
- 默认的移动构造函数以及移动赋值运算符会对非静态成员变量也尝试进行移动操作,如果非静态成员变量无法移动,将执行复制操作。
- 复制构造函数及复制赋值运算符是相互独立的,如果人为生成了其中一个,不会阻止编译器生成另一个。但为了更好的兼容性,我们应该都人为生成一下。
- 移动构造函数以及移动赋值运算符却是关联的,如果人工生成了其中一个,将阻止编译器为另外一个生成默认函数。因为编译器认为既然需要人为的自定义一个移动操作,那么说明默认移动操作不满足要求,为了避免编译器生成的默认函数与你设计不服,编译器将直接不生成。
- 一旦人为声明了复制构造函数或复制赋值运算符,编译器将被阻止生成默认的移动构造函数以及移动赋值运算符。因为编译器认为既然默认复制操作不满足条件,则移动操作也一定不满足条件。反之亦然,一旦人为声明了移动构造函数或移动赋值运算符,编译器将被阻止生成默认的复制构造函数及复制赋值运算符。
- 一旦人为声明了移动构造函数或移动赋值函数,编译器就会废除默认复制操作(delete 它们),因为编译器认为,默认的移动操作不能满足用户要求,理所当然的人为默认的复制操作也可能满足不了用户的要求。
- 大三律:如果你人为实现了复制构造函数、复制赋值运算符或析构函数中的任何一个,那么就得同时实现这三个。这一条在C++11上目前并没有硬性要求。
- 移动操作自动生成的条件:1.该类未声明任何复制操作 2.该类未声明任何移动操作 3.该类未声明任何析构函数
- 一旦声明了析构函数,编译器将被阻止生成移动操作,所有需要移动操作的地方,将全部被换为复制操作。
- 对特种成员函数使用=default来显示定义,编译器将为其生成默认函数。所以,如果确认默认特种函数满足要求,那我们最好对所有特种成员函数执行该操作,以避免编译报错或移动被复制替换等问题发生
- 如果我们声明了复制操作,就要将移动操作也声明出来,因为此时编译器将不会为我们生成默认移动操作,所有使用移动操作的地方将被复制替代。
- 成员函数模板在任何情况下都不会抑制特种成员函数的生成
Comments NOTHING