boost:smart_ptr库——两种智能指针

boost提供的智能指针都是轻量级的对象,速度与原始指针相差无几,都是异常安全的,对于所指向的类型也仅由一个要求:指向的类型T的析构函数不能抛出异常。

一、scoped_ptr

此智能指针包装了 new 操作符在堆上分配的动态对象,能够保证动态创建的对象在任何时候都可以被正确地删除。

scoped_ptr 对象的生命周期结束时,析构函数会使用 delete 操作符自动销毁所管理的对象,从而正确地回收资源。

其特点是不能转让,一旦获取了对象的管理权,就无法再从它那里取回来。因为它将拷贝构造函数和赋值操作符都声明为私有的,禁止对智能指针的拷贝操作。这也说明了如果一个类持有 scoped_ptr 成员变量,那么它也是不可拷贝和赋值的

scoped_ptr 不能用于容器,因为它不能拷贝和赋值。

#include <boost/smart_ptr.hpp>
using namespace boost;

class test
{
public:
    test(int value):value(value)
    {
    }
    void showValue()
    {
        qDebug()<<value;
    }
    ~test()
    {
        qDebug()<<"析构test value = "<<value;
    }
private:
    int value;
};

int main()
{
    scoped_ptr<test> sp(new test(666));

    //delete sp;//错误,因为sp不是一个指针

    if(sp)  //转为bool
        qDebug()<<"sp非空";

    sp.reset(new test(888));//重置
    test * p = sp.get();//获取原始指针
    p->showValue();
    sp->showValue();
}

二、shared_ptr

是boost最重要的智能指针,被添加到标准库了

scoped_ptr 一样包装了 new 操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针,可以被自由地拷贝和赋值,在任意的地方共享它,当引用计数为0时才删除被包装的动态分配的对象。

shared_ptr 也可以安全地放到标准容器中,是在STL容器中存储指针的最标准解法。

用法见:c++标准库智能指针:shared_ptr

2.1、工厂函数

一般地,new 创建出来的对象要 delete 销毁掉,智能指针消除了 delete 调用,如果使用者对对象只需要 new 不需要 delete 感到别扭,可以使用工厂函数创建对象,工厂函数消除了 new 的调用。

int main()
{
    auto sp = make_shared<test>(999);
    sp->showValue();
}

2.2、shared_ptr 用于容器的两种方式

int main()
{
    QList<shared_ptr<test>> list;
    list.append(make_shared<test>(111));
    list.append(make_shared<test>(222));
    list.first()->showValue();

    shared_ptr<QList<test*>> list2 = make_shared<QList<test*>>();
    list2->append(new test(444));
    list2->append(new test(555));
    list2->first()->showValue();
    qDeleteAll(*list2.get());
}

第二种还要手动释放,推荐使用第一种。

2.3、示例:shared_ptr 用于工厂方法

class abstract
{
public:
    virtual void f() = 0;
    virtual void g() = 0;
protected:
    virtual ~abstract() = default;
};

class impl:public abstract
{
public:
    impl() = default;
    virtual ~impl() = default;
public:
    virtual void f() 
    {   std::cout << "class impl f" << std::endl; }
    virtual void g() 
    {   std::cout << "class impl g" << std::endl; }
};

shared_ptr<abstract> create()
{   return make_shared<impl>();}

void main()
{
    auto p = create();
    p->f();
    p->g();

    abstract *q = p.get();

    //delete q; //错误,abstract的析构函数是protected的,除了它自己和它的子类,其他对象无权调用delete删除它    
    //除非强转为 impl 类型,然后delete(不建议的操作)
}

这里使用创建对象返回的是智能指针,避免了忘了 delete 导致内存泄漏的隐患。

2.4、定制删除器

shared_ptr 构造时可以传入一个函数作为删除器,它将在对象被删除时调用。

void deleter(test * t)
{
    qDebug()<<"调用删除器 ";
    t->showValue();
}

int main()
{
    shared_ptr<test> sp(new test(888),&deleter);
//    auto sp2 = make_shared<test>(999,&deleter);//不可用
}

2.5、shared_ptr<void>

shared_ptr<void> 能够存储 void* 型的指针,而 void* 型指针可以指向任意类型,因此 shared_ptr<void> 就像是一个泛型的指针容器,拥有容纳任意类型的能力。

但将指针存储为 void* 同时也丧失了原来的类型信息,为了在需要的时候正确使用,可以用转型函数重新转为原来的指针。但这涉及运行时动态类型转换,会使代码不够安全,建议最好不要这样使用。

2.6、转换类型函数

int main()
{
    shared_ptr<void> vp = make_shared<test>(666);
    shared_ptr<test> sp = static_pointer_cast<test>(vp);
    shared_ptr<test> sp2 = const_pointer_cast<test>(vp);
    shared_ptr<test> sp3 = dynamic_pointer_cast<test>(vp);
    
    //错误的:
//    shared_ptr<test> sp2 = static_cast<test>(vp);
//    shared_ptr<test> sp3 = static_cast<shared_ptr<test>>(vp);
}

2.7、删除器的高级用法

实现在vp析构时调用任何函数:

void any_func(void *)
{
    qDebug()<<"任何操作";
}

int main()
{
    shared_ptr<void> vp(nullptr,&any_func);
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值