c++11之unique_ptr智能指针使用

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值