boost:smart

boost:smart,第1张

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



一、scoped_ptr

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


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


其特点是不能转让,一旦获取了对象的管理权,就无法再从它那里取回来。


因为它将拷贝构造函数和赋值 *** 作符都声明为私有的,禁止对智能指针的拷贝 *** 作。


这也说明了如果一个类持有 scoped_ptr 成员变量,那么它也是不可拷贝和赋值的


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


#include 
using namespace boost;

class test
{
public:
    test(int value):value(value)
    {
    }
    void showValue()
    {
        qDebug()<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(999);
    sp->showValue();
}
2.2、shared_ptr 用于容器的两种方式
int main()
{
    QList> list;
    list.append(make_shared(111));
    list.append(make_shared(222));
    list.first()->showValue();

    shared_ptr> list2 = make_shared>();
    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 create()
{   return make_shared();}

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 sp(new test(888),&deleter);
//    auto sp2 = make_shared(999,&deleter);//不可用
}
2.5、shared_ptr

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


但将指针存储为 void* 同时也丧失了原来的类型信息,为了在需要的时候正确使用,可以用转型函数重新转为原来的指针。


但这涉及运行时动态类型转换,会使代码不够安全,建议最好不要这样使用。


2.6、转换类型函数
int main()
{
    shared_ptr vp = make_shared(666);
    shared_ptr sp = static_pointer_cast(vp);
    shared_ptr sp2 = const_pointer_cast(vp);
    shared_ptr sp3 = dynamic_pointer_cast(vp);
    
    //错误的:
//    shared_ptr sp2 = static_cast(vp);
//    shared_ptr sp3 = static_cast>(vp);
}
2.7、删除器的高级用法

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

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

int main()
{
    shared_ptr vp(nullptr,&any_func);
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/579038.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存