
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());
}
第二种还要手动释放,推荐使用第一种。
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 导致内存泄漏的隐患。
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_ptrshared_ptr 但将指针存储为 void* 同时也丧失了原来的类型信息,为了在需要的时候正确使用,可以用转型函数重新转为原来的指针。 但这涉及运行时动态类型转换,会使代码不够安全,建议最好不要这样使用。 实现在vp析构时调用任何函数: 欢迎分享,转载请注明来源:内存溢出
2.7、删除器的高级用法
int main()
{
shared_ptrvoid any_func(void *)
{
qDebug()<<"任何操作";
}
int main()
{
shared_ptr
微信扫一扫
支付宝扫一扫
评论列表(0条)