C++11/14/17中的特殊成员函数

Rationale(原理部分)
Rule of 3

如果隐式生成的析构函数,拷贝赋值算符,拷贝构造函数中任一不能正常工作,则三者均不能正常工作。

C++98中的generated special member function

由于在C++98诞生时,rule of 3的重要性没有被认识到,所以上述3者的显式声明对于编译器对它们的隐式生成没有干扰。举例来说,如果显式声明了一个析构函数,由rule of 3可知,拷贝赋值算符与拷贝构造函数肯定不能正常工作,但编译器依旧隐式生成这两者的默认版本。

C++11中的generated special member function

C++11诞生时,标准委员会已经充分认识到了rule of 3的重要性,并且由于C++11中 move semantics的引入,rule of 3 进化为 rule of 5,即析构函数,拷贝操作,移动操作5者中任一不能使用默认版本则全部不能使用默认版本,并且标准委员会通过标准来强制执行 rule of 5。

删除定义与默认定义

C++11还引入了两种新的函数定义模式,删除定义与默认定义(ISO 8.4.2, ISO 8.4.3)
形式上为
function declaration = default;
function declaration = delete;
形式上与之类似的还有纯虚函数(ISO 10.4)
function declaration = 0;

Specs(细则部分)

1.编译器会隐式定义没有被显式声明的特殊成员函数,除非被阻止(情况2)。
2.任何显式声明的构造函数阻止默认构造函数的隐式定义。(C++98)
3.Rule of 5 中任一函数的显式声明使得移动操作被隐式删除定义。(C++11)
4.移动操作的显式声明使得拷贝操作被隐式删除定义。(C++11)
5.情况3可能在C++17中扩展到拷贝操作上。(Future)

名词说明

1.特殊成员函数指的是构造函数,赋值算符和析构函数。
2.拷贝操作包括拷贝赋值与拷贝构造,移动操作与之同理。

实例分析

BS在他的第四版The C++ Programming Language中犯了一个错误,引发了我写这篇文章的想法,C++他爹也会犯错: )
TC++PL 4th
chap 28.2
page 783 中有如下一个模版类定义

template<typename T>
struct Scoped {
    //省略与主体无关的
   Scoped(const  Scoped &) = delete;
   Scoped & operator=(const Scoped &) = delete;         
}

C++他爹是想禁止Scoped的instance被拷贝,由细则部分第2条可知,这个类不能被默认构造,由于老爹又没提供其他的构造函数,也就是说。。这个类不能被构造。。 但是事实上他确实定义了Scoped的object。

g++ 4.8.3
clang 3.5
VS2013R4
行为均与标准一致,不过VS2013R4不支持默认定义移动操作,VS2015 Preview中已提供支持
最后附上测试代码

template<typename T>
class Test {
    //下边两行存在任意一行时,默认构造函数均不应该被隐式生成
    Test(const Test &) = delete;
    Test(Test &&) = delete;
};
 
int main() {
    Test<int> a;
    return 0;
  }

转载于:https://www.cnblogs.com/roger-chen/p/4149304.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值