1、资源和智能指针
1.1 资源获取即初始化(RAII)原则
资源获取即初始化(RAII, Resource Acquisition Is Initialization)。
资源(堆内存、文件句柄、套接字等)应由对象“拥有”。 该对象在其构造函数中创建或接收新分配的资源,并在其析构函数中将此资源删除。 RAII 原则可确保当所属对象超出范围时,所有资源都能正确返回到操作系统。
通俗理解:当你获得一个资源的时候,不管这个资源是对象、内存、文件句柄或者其它什么,你都会在一个对象的构造函数中获得它,并且在该对象的析构函数中释放它。实现这种功能的类,我们就说它采用了”资源获取即初始化(RAII)”的方式。这样的类常常被称为封装类。
2、统一初始化(括号初始化)
在现代 C++ 中,可以使用任何类型的括号初始化。 在初始化数组、矢量或其他容器时,这种初始化形式会非常方便。 在下面的示例中,使用三个 S 实例初始化 v2。 v3 将使用三个 S 实例进行初始化,这些实例使用括号初始化自身。 编译器基于 v3 声明的类型推断每个元素的类型。
#include <vector>
struct S
{
std::string name;
float num;
S(std::string s, float f) : name(s), num(f) {}
};
int main()
{
// C-style initialization
std::vector<S> v;
S s1("Norah", 2.7);
S s2("Frank", 3.5);
S s3("Jeri", 85.9);
v.push_back(s1);
v.push_back(s2);
v.push_back(s3);
// Modern C++:
std::vector<S> v2 {s1, s2, s3};
// or...
std::vector<S> v3{ {"Norah", 2.7}, {"Frank", 3.5}, {"Jeri", 85.9} };
}
3、移动语义
一句话:资源的所有权转移
现代 C++ 提供了移动语义,此功能可以避免进行不必要的内存复制。 移动操作会将资源的所有权从一个对象转移到下一个对象,而不必再进行复制。 一些类拥有堆内存、文件句柄等资源。 实现资源所属的类时,可以定义此类的移动构造函数和移动赋值运算符。 在解析重载期间,如果不需要进行复制,编译器会选择这些特殊成员。 如果定义了移动构造函数,则标准库容器类型会在对象中调用此函数。