APOLLO学习C++基础之一[unique_ptr智能指针]
在学习apollo过程中,经常碰到这样的指针,unique_ptr,就是我要讲的智能指针,(当然,对于C++的高手来说,就是小菜一碟,对于经常使用C的我,当然有点陌生,所以就一点一点的学习,一点一点的积累。)导航器指针(navigator_ptr_)、监控日志类对象(monitor_logger_)、路由配置类对象(routing_conf_)、高精地图指针(hdmap_)。注意navigator_ptr_使用C++标准库的唯一性智能指针unique_ptr包装。
智能指针其优点在于:
1)智能指针能够帮助我们处理资源泄露问题;
2)它也能够帮我们处理空悬指针的问题;
3)它还能够帮我们处理比较隐晦的由异常造成的资源泄露。
4)是不用人工管理内存;
5)确保数据的唯一性。如导航器指针(std::unique_ptr<Navigator> navigator_ptr_)
1.智能指针unique_ptr的用法
unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法:
std::unique_ptr<T> myPtr(new T);
std::unique_ptr<T> myOtherPtr = myPtr; // 错误用法
但是unique_ptr允许通过函数返回给其他的unique_ptr,还可以通过std::move来转移到其他的unique_ptr,注意,这时它本身就不再拥有原来指针的所有权了。相比于auto_ptr而言,unique_ptr是显示的转移,而不是莫名其妙的报废,因为auto_ptr调用拷贝构造函数后,原来的对象就失效了。
std::unique_ptr<T> myPtr(new T);
std::unique_ptr<T> myOtherPtr = std::move(myPtr); //这样使用是正确的
对于一般的程序使用std::unique_ptr就够了,如果是多线程方面,可能存在共同使用的问题,可以使用std::shared_ptr,注意不要引起循环引用。
2.管理数组指针
因为unique_ptr有unique_ptr< X[ ] >重载版本,销毁动态对象时调用delete[],所以可以用unique_ptr来管理数组指针。
unique_ptr< Test[ ] > uptr1(new Test[3]);
//注意 unique_ptr<Test> uptr3(new Test[3]);是不对的
unique_ptr<int[]> uptr2(new int[5]);
3.做容器(vector, list, map)元素
vector<unique_ptr<int> > vec;
unique_ptr<int> ptr1(new int(3));
vec.push_back(std::move(ptr1));
//vec.push_back(ptr1); //由于禁止复制这样不行
unique_ptr类中有get()、reset()、release()等函数。
get(): 获得原生指针
reset():重置,显式释放资源
reset(new XX):重置,重新指定对象
release():释放所有权到某一原生指针上
另外可以通过std::move将所有权由一个unique_ptr对象转移到另一个unique_ptr对象上,具体见下例。
#include <iostream>
#include <memory>
using namespace std;
int main()
{
//1. unique_ptr的创建
//1.1)创建空的,然后利用reset指定对象
unique_ptr<int> up1;
up1.reset(new int(3));
//1.2)通过构造函数在创建时指定动态对象
unique_ptr<int> up2(new int(4));
//2. 获得原生指针(Getting raw pointer )
int* p = up1.get();
//3.所有权的变化
//3.1)释放所有权,执行后变为empty
int *p1 = up1.release();
//3.2)转移所有权,执行后变为empty
unique_ptr<int> up3 = std::move(up2);
//4.显式释放资源
up3.reset();
return 0;
}
4.禁止赋值和复制
unique_ptr禁止赋值和复制,“唯一”地拥有其所指对象,同一时刻只能有一个unique_ptr实例指向给定对象。也就是说模板类unique_ptr的copy构造函数以及等号(“=”)操作符是无法使用的。
通过禁止复制和赋值可以较好的改善auto_ptr的所有权转移问题。下面是其禁止复制和赋值的例子:
#include <iostream>
#include <memory>
using namespace std;
void Fun1( unique_ptr<int> up )
{
}
int main()
{
unique_ptr<int> up1 = unique_ptr<int>(new int(10));
//不允许复制(Copy construction is not allowed),所以以下三个均错误
unique_ptr<int> up2 = up1; // 错误
unique_ptr<int> up3(up1); // 错误
Fun1(up1); // 错误
//不允许赋值('='),所以下面错误
unique_ptr<int> up4;
up4 = up1; // 错误
return 0;
}