传统指针具有以下缺陷:
- 单从一个指针的声明,无法判定它是指向一个对象还是指向一个包含该对象的数组
- 单从一个指针的声明,无法判定当不使用该指针时,是否需要释放它所指向对象所占用的资源
- 当需要释放指针所指向对象的资源时,并不能明确的知道是该使用
delete
,还是使用其它专有的释放函数 - 当需要使用
delete
释放资源时,到底是使用delete
还是delete[]
,这需要小心使用 - 当确定了释放机制时,也有可能写代码时一不小心,就造成了 double free
- 当释放一个资源时,有可能还有其它指针指向该资源,从而导致很多很难查的 BUG
使用智能指针变能够最大化的避免以上问题。
unique_ptr
的特点
unique_ptr
和原始指针的大小一样大,并且执行效率也高,可以满足一些对内存和运行性能有要求的场合。unique_ptr
属于独占所指向的资源,因此不能将其赋值给另外的unique_ptr
,而只能使用移动语义
unique_ptr
的使用场合
在工厂函数中使用
一般工厂函数都会返回一个unique_ptr
,使用者可以没有心理负担的正常使用。
当该unique_ptr
退出代码块后,便会自动调用析构函数来释放其所指向的资源。而不用担心中途的异常发生而非正常的跳出该代码块。
当某些资源不能使用正常的delete
释放时,用户可以定义自己的delete function
:
1 | auto delInvmt = [](Investment* pInvestment) // custom |
在 c++14 中,则可以使用更加智能的推导方式:
1 | template<typename... Ts> |
使用lambda
来定义删除函数的好处是:使用该种方式不会使得unique_ptr
的体积增加,而使用普通函数的定义方式则会使得unique_ptr
的体积增加。
工厂函数之所以返回的是unique_ptr
,是因为这种返回方式可以不用关心调用者使用的是shared_ptr
还是unique_ptr
,这样更能适用于更加广泛的场合。
对数组使用
对数组使用的方式是std::unique_ptr<T[]>
,一般使用这种方式都是在使用该指针指向 c 代码所提供的从堆中申请的内存地址。