在学习c++的过程中时不时冒出一些概念和常用语,但是却苦于不得其解,这里整理一下.主要来源是cppreference.
三/五/零原则
三原则
如果某个类需要用户定义的析构函数、用户定义的复制构造函数或用户定义的复制赋值运算符,那么它几乎肯定需要全部三个。1
2
3
4
5
6
7
8
9
10
11
12
13class MyLockGuard {
public:
using mutext_type = T;
explicit MyLockGuard(T t_mutex) : _MyMutex(t_mutex) { _MyMutex.lock(); }
MyLockGuard(T& _Mtx, std::adopt_lock_t) noexcept : _MyMutex(_Mtx) {}
MyLockGuard(const MyLockGuard&) = delete;
MyLockGuard& operator=(const MyLockGuard&) = delete;
~MyLockGuard() noexcept { _MyMutex.unlock(); }
private:
T& _MyMutex;
};
五复制
因为用户定义(包括 = default 或 = delete)的析构函数、复制构造函数或复制赋值运算符,会阻止隐式定义移动构造函数和移动赋值运算符,所以任何想要移动语义的类必须声明全部五个特殊成员函数
与三原则不同的是,不提供移动构造函数和移动赋值运算符通常不是错误,但会损失性能。
零原则
有自定义析构函数、复制/移动构造函数或复制/移动赋值运算符的类应该专门处理所有权(这遵循单一责任原则)。其他类都不应该拥有自定义的析构函数、复制/移动构造函数或复制/移动赋值运算符
当有意将某个基类用于多态用途时,可能需要将它的析构函数声明为 public 和 virtual。由于这会阻止生成隐式移动(并弃用隐式复制),因此必须将各特殊成员函数定义为 = default
类模板实参推导(CTAD)
为了实例化一个类模板,需要知晓每个模板实参,但并非每个模板实参都必须指定。在下列语境中,编译器会从初始化式的类型推导缺失的模板实参:
- 任意指定变量及变量模板的初始化的声明,其声明的类型是类模板(可有 cv 限定)