《Effective Modern C++》学习笔记之条款十七:理解特种成员函数的生成机制

本文详细解析C++中的特种成员函数,包括默认构造函数、析构函数、复制构造函数等,并探讨它们的生成条件与特点。特别是对于移动构造函数与移动赋值运算符之间的关联进行了深入讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiang木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值