C++Smart Pointer智能指针怎么用(C++,smart,开发技术)

时间:2024-05-08 00:49:08 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

    一、为啥使用智能指针呢

    标准库中的智能指针:std::auto_ptr--singleownership(C++98中出现,缺陷较多,被摒弃)std::unique_ptr--singleownership(C++11替代std::auto_ptr,用于单线程)std::shared_ptr--sharedownership(C++11,用于多线程)std::weak_ptr--temp/noownership(C++11)IntroducedinC++11Definedin<memory>header.

    首先看一个下面的栗子,左边是木有使用智能指针的情况,当执行foo()函数,其中的e指针会在bar(e)时传入bar函数,但是在bar函数结束后没有人为delete e时,就会导致内存泄漏;但是在右边的栗子中,使用了unique_ptr智能指针(single ownership),就能防止内存泄漏。

    C++Smart Pointer智能指针怎么用

    智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。

    • auto_ptr智能指针:(C++11出来前只有这种智能指针)当对象拷贝或者赋值后,前面的对象就悬空了。

    • unique_ptr智能指针:防止智能指针拷贝和复制。

    • shared_ptr智能指针:通过引用计数的方式来实现多个shared_ptr对象之间共享资源。

    • weak_ptr智能指针:可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用记数的增加或减少。

    注意:每一种智能指针都可以增加内存的引用计数。

    • 智能指针分为两类:

      • 一种是可以使用多个智能指针管理同一块内存区域,每增加一个智能指针,就会增加1次引用计数,

      • 另一类是不能使用多个智能指针管理同一块内存区域,通俗来说,当智能指针2来管理这一块内存时,原先管理这一块内存的智能指针1只能释放对这一块指针的所有权(ownership)。

    • 按照这个分类标准,auto_ptrunique_ptrweak_ptr属于后者,shared_ptr属于前者。

    shared_ptr进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类。可以通过make_shared函数或者通过构造函数传入普通指针。并可以通过get函数获得普通指针。

    #include<string>#include<memory>usingnamespacestd;classreport{private:stringstr;public:report(conststrings):str(s)//构造方法{cout<<"1reportObjecthasbeenbuild!"<<endl;}~report(){cout<<"3reportObjectdeleted!"<<endl;}voidtalk(){cout<<str<<endl;}};intmain(){stringtalk="2hello,thisisatest!";{auto_ptr<report>ptr(newreport(talk));ptr->talk();}{shared_ptr<report>ptr(newreport(talk));ptr->talk();}{unique_ptr<report>ptr(newreport(talk));ptr->talk();}return0;}

    C++Smart Pointer智能指针怎么用

    二、shared_ptr智能指针

    shared_ptr实现了共享拥有的概念,利用“引用计数”来控制堆上对象的生命周期。

    share_ptr的生命周期:

    C++Smart Pointer智能指针怎么用

    原理:在初始化的时候引用计数设为1,每当被拷贝或者赋值的时候引用计数+1,析构的时候引用计数-1,直到引用计数被减到0,那么就可以delete掉对象的指针了。他的构造方式主要有以下三种:

    shared_ptr<Object>ptr;shared_ptr<Object>ptr(newObject);shared_ptr<Object>ptr(newObject,[=](Object*){//回收资源时调用的函数});autoptr=make_shared<Object>(args);
    • 第一种空构造,没有指定shared_ptr管理的堆上对象的指针,所以引用计数为0,后期可以通过reset()成员函数来指定其管理的堆上对象的指针,reset()之后引用计数设为1。

    • 第二种是比较常见的构造方式,构造函数里面可以放堆上对象的指针,也可以放其他的智能指针(如weak_ptr)。

    • 第三种构造方式指定了shared_ptr在析构自己所保存的堆上对象的指针时(即引用计数为0时)所要调用的函数,这说明我们可以自定义特定对象的特定析构方式。同样的,reset()成员函数也可以指定析构时调用的指定函数。

    • 第四种方法:较常见,构造shared_ptr的方式(最安全):

    autoptr=make_shared<Object>(args);

    上面第四种方法,使用标准库里边的make_shared<>()模板函数。该函数会调用模板类的构造方法,实例化一个堆上对象,然后将保存了该对象指针的shared_ptr返回。参数是该类构造函数的参数,所以使用make_shared<>()就好像单纯地在构造该类对象一样。auto是C++11的一个关键字,可以在编译期间自动推算变量的类型,在这里就是shared_ptr<Object>类型。

    C++Smart Pointer智能指针怎么用

    shared_ptr的其他成员函数:

    use_count() //返回引用计数的个数unique() //返回是否是独占所有权(use_count是否为1)swap() //交换两个shared_ptr对象(即交换所拥有的对象,引用计数也随之交换)reset() //放弃内部对象的所有权或拥有对象的变更,会引起原有对象的引用计数的减少

    三、unique_ptr智能指针

    注意unique_ptr是single ownership的,不能拷贝。其构造方式如下:

    C++Smart Pointer智能指针怎么用

    unique_ptr的生命周期:

    C++Smart Pointer智能指针怎么用

    四、weak_ptr智能指针

    C++Smart Pointer智能指针怎么用

    五、智能指针怎么解决交叉引用,造成的内存泄漏

    结论:创建对象时使用shared_ptr强智能指针指向,其余情况都使用weak_ptr弱智能指针指向。

    5.1 交叉引用的栗子:

    当A类中有一个指向B类的shared_ptr强类型智能指针,B类中也有一个指向A类的shared_ptr强类型智能指针。

    main函数执行后有两个强智能指针指向了对象A,对象A的引用计数为2,B类也是:

    #include<iostream>#include<memory>usingnamespacestd;classB;classA{public:shared_ptr<B>_bptr;};classB{public:shared_ptr<A>_aptr;};intmain(){shared_ptr<A>aptr(newA());shared_ptr<B>bptr(newB());aptr->_bptr=bptr;bptr->_aptr=aptr;return0;}

    C++Smart Pointer智能指针怎么用

    而当主函数mainreturn返回后,对象A的引用计数减一变为1(aptr没指向A对象了),B对象也是,引用计数不为0,即不能析构2个对象释放内存,造成内存泄漏。

    5.2 解决方案

    将类A和类B中的shared_ptr强智能指针都换成weak_ptr弱智能指针;

    classA{public:weak_ptr<B>_bptr;};classB{public:weak_ptr<A>_aptr;};

    weak_ptr弱智能指针,虽然有引用计数,但实际上它并不增加计数,而是只观察对象的引用计数。所以此时对象A的引用计数只为1,对象B的引用计数也只为1。

    C++Smart Pointer智能指针怎么用

    六、智能指针的注意事项

    • 避免同一块内存绑定到多个独立创建的shared_ptr上,因此要不使用相同的内置指针初始化(或reset)多个智能指针,不要混合使用智能指针和普通指针,坚持只用智能指针。

    • 不delete get() 函数返回的指针,因为这样操作后,shared_ptr并不知道它管理的内存被释放了,会造成shared_ptr重复析构。

    • 不使用 get()函数初始化或(reset)另外的智能指针。

    shared_ptr<int>p=make_share<int>(42);int*q=p.get();{shared_ptr<int>(q);}//程序块结束,q被销毁,指向的内存被释放。intfoo=*p;//出错,p指向的内存已经被q释放,这是用get()初始化另外的智能指针惹得祸。//请记住,永远不要用get初始化另外一个智能指针。

    能使用unique_ptr时就不要使用share_ptr指针(后者需要保证线程安全,所以在赋值or销毁时overhead开销更高)。

     </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
    本文:C++Smart Pointer智能指针怎么用的详细内容,希望对您有所帮助,信息来源于网络。
    上一篇:feign参数过多导致调用失败怎么办下一篇:

    9 人围观 / 0 条评论 ↓快速评论↓

    (必须)

    (必须,保密)

    阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18