参考
RAII(Resource Acquisition is Initialization)
RAII的字面意思是资源获取与对象初始化绑定。即对象创建后立刻得到其所需的资源。实际意义上讲,RAII是将堆上资源的所有权交给栈上对象。该对象的析构函数中含有释放此堆上资源的方法。
智能指针
智能指针在头文件<memory>
中命名空间std
下被定义,对RAII机制至关重要。在获取堆上资源时,应立即将指向该资源的普通指针传递给一个智能指针对象,该智能指针将会负责在离开其作用域时或者程序抛出异常时释放所申请的堆上资源。从而避免任何可能的内存泄漏,包括人为忘记释放该资源等。
class LargeObject
{
public:
void DoSomething(){
}
};
void ProcessLargeObject(const LargeObject& lo){
}
void SmartPointerDemo()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
//Call a method on the object
pLarge->DoSomething();
// Pass a reference to a method.
ProcessLargeObject(*pLarge);
} //pLarge is deleted automatically when function block goes out of scope.
官方文档中的示例展示了:
- 将智能指针声明为局部变量;
- 需要指明智能指针所封装的指针所指的数据类型;
- 将指向用
new
申请的资源的普通指针传递给智能指针进行初始化构造; - 之后就可以把这个只能指针当作普通指针来用啦;
- 在离开作用域后,再也不怕忘记释放空间而导致内存泄漏啦!
对于unique_ptr<>
,其成员变量仅有被封装的普通指针,因此使用智能指针对性能上的影响并不明显。同时它还带有成员函数,可以使用.
访问,例如
// Free the memory before we exit function block.
pLarge.reset();
可以实现在任意时刻提前释放掉所申请的资源。
对于无法传入智能指针的API,智能指针也提供直接访问其封装的普通指针的方法以便兼容地传入。
// Pass raw pointer to a legacy API
LegacyLargeObjectFunction(pLarge.get());
std::unique_ptr
std::unique_ptr
封装的普通指针只能属于唯一一个智能指针对象。在非必要使用shared_ptr
时,默认使用unique_ptr
。支持move
,无法拷贝,构造unique_ptr
时最好使用helper函数make_unique()
,因为其支持异常处理,比直接将指针丢入unique_ptr
构造更安全。
若要构造一个unique_ptr
,make_unique
可以传入指针所指对象的构造所需参数。
auto lo = make_unique<LargeObject>