类的特殊成员函数
在C++中定义一个类,会默认生成以下6个成员函数:
- 默认构造函数
- 析构函数
- 复制构造函数
- 复制赋值运算符函数
- 移动构造函数(C++11 新增)
- 移动赋值运算符函数(C++11 新增)
这些功能很实用,在我们直接定义一个类之后,能够直接互相拷贝,而不用为了编译器语法的原因一定要写一遍这些函数。
但是它也有一些潜规则:
- 声明任何构造函数都会抑制默认构造函数的添加。
- 一般用自定义的构造函数替代默认构造函数,类就会转化为非平凡类型。
非平凡类
什么是平凡类什么是非平凡类呢?
这里的概念是出自C语言,C语言想要复制一个对象最快速的方法是直接把整个对象的内存从a复制到b,而不用考虑其他的情况。
但是对C++的类,可能就不能通过直接复制对象的内存来实现复制,因为类可能定义了构造函数、复制构造函数,要在直接的内存copy之前或者之后做一些逻辑,甚至可能是很重的逻辑,那么对象的拷贝就只能通过复制构造函数来做了。
因此,平凡类和非平凡类的最大差别是:是否能直接copy类的内存块来实现完整的复制,想做到这个要求这个类在构造的时候和复制的时候不需要做额外的逻辑,但是编译器无法确认你是否有做了额外的逻辑,所以编译器只能定义,显式(explict)定义了四种函数:
- 构造函数
- 复制构造函数
- 复制赋值函数
- 析构函数
有另外定义就是非平凡类,但是如果定义了使用=default,也算是默认的,所以不会改变平凡类的性质。
从我这个角度去分析这个问题应该会简单一点。
POD是指完全跟C语言的struct兼容,需要是平凡类和标准布局,这俩分别对应的是行为定义和内存定义。
显示默认和显示删除
C++11标准提供了一种简单的方法能够有效地控制默认特殊函数的添加和删除,语法很简单,就是在尾部添加=default和=delete。
这里=default可以在.cpp中去制定,但是=delete必须在.h中指定,不过这个也很好理解。
显示删除除了在这些地方,还可以使用在普通函数上,可能是给一些库使用,保留旧的函数签名,但是链接新版本时会失败,虽然听起来还是没什么用。
然后就是可以显式的删除new函数和析构函数,而且这两者的表现完全相反,new操作符被删除之后,就不能通过new创建了,只能通过自动变量、静态变量等方法创建;而析构函数删除后,则无法调用delete函数,同时也无法从自动变量、全局变量中创建。
参考了一下维基百科里C++的new,原来C++ new一个过程是先用operator new创建内存,然后调用构造函数再返回指针,而new 操作还支持在已经有的内存上直接new一个对象……
参考
https://zh.wikipedia.org/wiki/POD_(%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1)
https://zh.wikipedia.org/wiki/New_(C%2B%2B)
End。