????????智能指针可以帮助管理动态分配的内存,是避免内存泄漏的有用技术。智能指针可用于管理在函数作用域内(或作为类的数据成员)动态分配的资源,当智能指针离开作用域或者被重置时,会自动释放所占用的资源。
????????智能指针有多种类型。最简单的智能指针类型std::unique_ptr对资源有唯一的所有权,稍微高级点的智能指针允许共享所有权,即多个智能指针指向同一个资源,当这样的智能指针离开作用域或者被重置时,仅当它是指向该资源的最后一个智能指针时,才会释放指向的资源,标准库提供了std::shared_ptr,它支持共享所有权。
????????应将unique_ptr用作默认智能指针,仅当需要共享资源时,才使用shared_ptr。使用智能指针需添加<memory>头文件
? ? ? ? unique_ptr拥有唯一的所有权,当unique_ptr被销毁或重置时,自动释放资源。它的一个优点是,内存和资源总会被释放,即使在执行return语句或抛出异常时也是如此。例如,当函数有多个return语句时,不必在每个return语句之前都写一个释放资源的动作,简化了编码过程。
????????参考下面的函数,在自由存储区上分配了一个Simple对象,并且有调用delete,你可能认为代码正确地释放了内存,但这个例子仍然可能会产生内存泄漏!如果go()方法抛出异常,将永远不会调用delete,导致内存泄漏。
void func(){
Simple* mySimplePtr = new Simple();
mySimplePtr->go();
delete mySimplePtr;
}
????????下面的函数使用了unique_ptr,Simple对象不会显式地释放,但unique_ptr实例在离开作用域或遇到异常时,就会在其析构函数种自动释放Simple对象。unique_ptr通过std::make_unique()辅助函数创建。
void func(){
auto mySmartPtr = make_unique<Simple>();
mySmartPtr->go();
}
????????像标准指针一样,仍可以使用*或者->对智能指针进行解引用。
mySmartPtr->go();
(*mySmartPtr).go();
????????get()方法,可用于直接获得底层指针。可将指针传递给需要普通指针的函数。
void func(Simple* simple){
...
}
// 可采用如下方式调用
func(mySmartPtr.get())
????????reset()方法,可释放unique_ptr的底层指针,并根据需要改成另一个指针。
mySmartPtr.reset(); // 释放资源并且指向nullptr
mySmartPtr.reset(new Simple()); // 释放资源并且指向一个新的Simple实例
????????release()方法,断开unique_ptr与底层指针的连接。它返回底层指针,并将智能指针设置为nullptr,则智能指针失去了对资源的所有权,需要在使用完资源时手动释放。
Simple* simple = mySmartPtr.release(); // 释放智能指针对资源的所有权
...
delete simple; // 手动释放
simple = nullptr;
????????由于unique_ptr代表唯一拥有权,因此无法复制它!但是可以用移动语义将一个unique_ptr移动到另一个,std::move()函数可以显式移动unique_ptr所有权。 ? ? ? ? ?