只是声明一个空类,不做任何事情的话,编译器会自动为你生成一个默认构造函数、一个默认拷贝构造函数、一个默认重载赋值操作符函数和一个默认析构函数。这些函数只有在第一次被调用时,才会被编译器创建,当然这几个生成的默认函数的实现就是什么都不做。所有这些函数都是 inline 和 public 的。
我们不希望对象被显示构造(单列模式)或赋值,可以将对应函数声明为private,或者写一个基类,开放部分默认函数,子类去继承就可以了。C++11新增标识符default和delete,控制这些默认函数是否使用。
- default:被标识的默认函数将使用类的默认行为,如:A() = default;
- delete:被标识的默认函数将禁用,如:A() = delete;
- override:被标识的函数需要强制重写基类虚函数;
- final:被标识的函数禁止重写基类虚函数;
在 C++ 11 中,一个类有八个默认函数:
- 默认构造函数;
- 默认拷贝构造函数;
- 默认析构函数;
- 默认重载赋值运算符函数;
- 默认重载取址运算符函数;
- 默认重载取址运算符const函数;
- 默认移动构造函数(C++11);
默认重载移动赋值操作符函数(C++11)。 ```cpp class A { public:
// 默认构造函数; A();
// 默认拷贝构造函数 A(const A&);
// 默认析构函数 ~A();
// 默认重载赋值运算符函数 A& operator = (const A&);
// 默认重载取址运算符函数 A* operator & ();
// 默认重载取址运算符const函数 const A* operator & () const;
// 默认移动构造函数 A(A&&);
// 默认重载移动赋值操作符 A& operator = (const A&&);
};
<a name="UQgEa"></a>
## 拷贝构造函数
复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中(包括按值传递参数),而不是常规的赋值过程中。类的复制构造函数原型通常如下:
```cpp
Class_name(const Class_name &);
赋值运算符重载
赋值运算符原型如下:
Class_name & Class_name::operator=(const Class_name &);
取地址操作符重载
const Class_name * operator & () const;
const 修饰的取地址操作符
在成员函数后面加 const,const 修饰 this 指针所指向的对象,也就是保证调用这个 const 成员函数的对象在函数内不会被改变。
移动构造函数和重载移动赋值操作符函数
- C++11 新增move语义:源对象资源的控制权全部交给目标对象,可以将原对象移动到新对象, 用于a初始化b后,就将a析构的情况;
- 移动构造函数的参数和拷贝构造函数不同,拷贝构造函数的参数是一个左值引用,但是移动构造函数的初值是一个右值引用;
- 临时对象即将消亡,并且它里面的资源是需要被再利用的,这个时候就可以使用移动构造。移动构造可以减少不必要的复制,带来性能上的提升。
左值引用和右值引用
带右值引用参数的拷贝构造和赋值重载函数,又叫移动构造函数和移动赋值函数,这里的移动指的是把临时量的资源移动给了当前对象,临时对象就不持有资源,为nullptr了,实际上没有进行任何的数据移动,没发生任何的内存开辟和数据拷贝。
参考:
https://zhuanlan.zhihu.com/p/97128024
https://nettee.github.io/posts/2018/Understanding-lvalues-and-rvalues-in-C-and-C/