unique_ptr介绍
在不能共享指针的情况下,我们可以使用c++11提供的unique_ptr智能指针。与share_ptr不同的是,某个时刻只能有一个unique_ptr指向一个给定的对象,当unique_ptr被销毁时它所指向的对象也被销毁。
unique_ptr相对shared_ptr独有的操作:
//空unique_ptr,u1使用delete来释放T类型的指针
unique_ptr<T> u1;
//用T*指针,和类型D的对象d来初始化u2,此时使用d来替代模式的deleter删除器;
unique_ptr<T,D> u2(T*, d);
//u放弃当前指针的控制权,并将u置空,返回所管理的指针,
u.release()
//释放u指向的对象
u.reset()
//令u指向q所管理的对象,q是普通的指针
u.reset(q);
在unique_ptr中,我们不可以使用赋值和拷贝构造unique_ptr对象,但是我们可以通过reset或者release函数将指针的所有权从unique_ptr转移给另一个unique_ptr,实例如下:
若release函数的返回值没有被unique_ptr对象接收,我们需要手动释放内存,否则有内存泄漏。
//使用默认的delete删除器,c++11中智能用new来初始化
unique_ptr<int> up1(new int(42));
unique_ptr<int> up2;
cout << "up1: " << *up1 << endl;
//不支持拷贝和赋值
/*
up2 = up1;
unique_ptr<int> up3(up1);
*/
//所有权转移
//up1的所有权转移到up2,up1不再管理指针,up1为空
//release的返回值是普通类型的指针
up2.reset(up1.release());
if(!up1)
{
cout << "up1 is null\n";
}
if(up2)
{
cout << "up2 is valid obj: " << *up2 << "\n";
}
//reset操作释放了up2原来指向的内存,并指向新的内存空间
up2.reset(new int(100));
if(up2)
{
cout << "up2 is valid obj: " << *up2 << "\n";
}
运行结果:
up1: 42
up1 is null
up2 is valid obj: 42
up2 is valid obj: 100
函数返回unique_ptr
不能执行拷贝unique_ptr的规制有一个例如:我们可以拷贝和赋值一个将要被销毁的unque_ptr。最常见的例子就是函数的返回值,如下:
//执行特殊的"拷贝构造",ok
unique_ptr<int> getResult()
{
unique_ptr<int> up(new int(100));
return up;
//return unique_ptr<int>(new int(100));
}
//测试代码:
auto up3 = getResult();
if(up3)
{
//get result: 100
cout << "get result: " << *up3 << endl;
}
定制自己的删除器
unique_ptr智能指针中也可以定制自己的删除器,其删除器的定制是在定义对象时确定的,作为模板参数之一,不能动态变更的,这个和shared_ptr定制删除器有区别,unique_ptr定制删除器如下:
//传递自己的删除器
//定义函数对象 返回值:void 入参:int*
std::function<void (int*)> deleter = [](int *pInt)
{
if (pInt != nullptr)
{
cout << "it is unique ptr deleter " << *pInt << "\n";
delete pInt;
pInt = nullptr;
}
};
//第二个模板参数是函数对象类型声明
unique_ptr<int, std::function<void (int*)> > up(new int(10), deleter );
up.reset();
运行结果:
it is unique ptr deleter 10
在shared_ptr智能指针中,定制删除器是运行时动态确定的,定义对象时不需要删除器的类型。
//创建时定制删除器
shared_ptr<T> p(q,d);//p接管了是普通指针p,p在析构时调用函数对象d来代替delete
shared_ptr<T> p(q2,d);//p是q2的拷贝,q2是shared_ptr类型,p在析构时调用函数对象d来代替delete。
//reset时定制删除器
p.reset(q,d);//令p指向普通指针q,将来用删除器d来释放q所指的指针,而不是delete。
shared_ptr定制删除器如下:
//定义函数对象 返回值:void 入参:int*
std::function<void (int*)> deleter = [](int *pInt)
{
if (pInt != nullptr)
{
cout << "it is deleter " << *pInt << "\n";
delete pInt;
pInt = nullptr;
}
};
//case 1
shared_ptr<int> p1(new int(10), deleter);
//call function deleter
p1.reset();
//case2
p1.reset(new int(20), [](int* p){
cout << "it new deleter..." << *p<<"\n";
delete p;
p = nullptr;
});
//call lambda deleter
p1.reset();
运行结果:
it is deleter 10
it is new deleter 20