zoukankan      html  css  js  c++  java
  • boost智能指针

    1.关于智能指针

       智能指针是存储“指向动态分类(在堆上)的对象的指针”。类似与普通指针,不同的是它们会在适当的时间自动回收空间。智能指针在面对出现异常情况下有着较好的下效果,可以确保动态分配的对象被析构。

    2.scoped_ptr

    • scoped_ptr存储一个指向动态分配对象的指针,在scoped_ptr析构过程中,或者reset,需要保证它所指的对象被删除;
    • scoped_ptr实际上是对裸指针的包装,但是限制了指针的复制行为;
    • 和std::auto_ptr类似,但没有所有权的转移的行为;
    • scoped_ptr不能复制,所以不能当作容器元素。
    #include <iostream>
    #include <boost/scoped_ptr.hpp>
    struct A{
        A(){
            std::cout << "A::A()" << std::endl;
        }
        ~A(){
            std::cout << "A::~A()" << std::endl;
        }
        void f(){
            std::cout << "A::f()" << std::endl;
        }
    };
    int main(){
        boost::scoped_ptr<int> sp(new int(128)); // 建议使用
        std::cout << ++(*sp) << std::endl;
        // Error 由于scoped_ptr将拷贝和赋值构造均设置为private,一个对象只能被一个只能指针包含
        // boost::scoped_ptr<int> sp2(sp);
        boost::scoped_ptr<A> ap(new A); // 建议使用
        ap->f();
        std::cout << " --------------- " << std::endl;
        // 由于对象a是栈上的对象,会自行析构,若在采用智能指针指向,会两次析构
        // A a;
        // boost::scoped_ptr<A> ap2(&a); // Error free(): invalid pointer
        // 可以这样作,但是尽量不要,由于A对象的指针a暴露在外面,会可能产生其他操作,导致问题出现
        A* a = new A;
        boost::scoped_ptr<A> ap2(a);
    }
    // 输出
    129
    A::A()
    A::f()
     ---------------
    A::A()
    A::~A()
    A::~A()

    3.shared_ptr

       shared_ptr可以多个智能指针管理同一个对象,并通过计数统计有多少个智能指针管理该对象,只有当计数为0时,所指对象指针会被析构。

      由于可以复制,因此shared_ptr可以和标准库中容器一起工作

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    struct A{
        A(){
            std::cout << "A::A()" << std::endl;
        }
        ~A(){
            std::cout << "A::~A()" << std::endl;
        }
        void f(){
            std::cout << "A::f()" << std::endl;
        }
    };
    int main(){
        boost::shared_ptr<int> sp(new int(128)); // 建议使用
        std::cout << ++(*sp) << std::endl;
        boost::shared_ptr<int> sp2(sp);
        std::cout << sp2.use_count() << std::endl; // 引用计数
        boost::shared_ptr<A> ap(new A); // 建议使用
        ap->f();
        std::cout << " --------------- " << std::endl;
    }
    // 输出
    129
    2
    A::A()
    A::f()
     ---------------
    A::~A()

    4.make_shared

       使用shared_ptr可以消除对显示delete的使用,但是没有避免现实new的支持,必须通过如下等方式构建:

     boost::shared_ptr<A> ap(new A);

    因此,通过make_shared()解决这个问题。

      头文件<boost/make_shared.hpp>提供了一组重载函数模板,make_shared使用operator new来分配内存。

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    #include <boost/make_shared.hpp>
    #include <string>
    using namespace std;
    
    class Cls1{
    public:
        Cls1(){
            cout << "Cls1()" << endl;
        }
        Cls1(int age,string name):_age(age),_name(name){
            cout << "Cls1(int age,string name)" << endl;
        }
        ~Cls1(){
            cout << "~Cls1()" << endl;
        }
    private:
        int _age;
        string _name;
    };
    class Cls2{
    public:
        Cls2(){
            cout << "Cls2()" << endl;
        }
        Cls2(int age):_age(age){
            cout << "Cls2(int age)" << endl;
        }
        ~Cls2(){
            cout << "~Cls2()" << endl;
        }
    private:
        int _age;
    };
    int main(){
        // 调用Cls1的无参构造
        boost::shared_ptr<Cls1> clp = boost::make_shared<Cls1>();
        // 调用Cls1的带有两个构造
        boost::shared_ptr<Cls1> clp1 = boost::make_shared<Cls1>(10,"ai");
        // 调用Cls2的带有一个构造
        boost::shared_ptr<Cls2> clp2 = boost::make_shared<Cls2>(10);
        return 0;
    }

    5.shared_ptr循环引用问题

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    using namespace std;
    class B;
    class A{
    public:
        A(){
            cout << "A()" << endl;
        }
        ~A(){
            cout << "~A()" << endl;
        }
        boost::shared_ptr<B> pb;
    };
    class B{
    public:
        B(){
            cout << "B()" << endl;
        }
        ~B(){
            cout << "~B()" << endl;
        }
        boost::shared_ptr<A> pa;
    };
    
    int main(){
        boost::shared_ptr<A> a(new A);
        boost::shared_ptr<B> b(new B);
        a->pb = b;
        b->pa = a;
        cout << a.use_count() << endl;
        cout << b.use_count() << endl;
        cout << "---------------" << endl;
        return 0;
    }
    //输出
    A::A()
    B()
    2
    2
    --------------

      从上述结果可以看出,最后new出来的A和B的对象均没有被析构。是由于a的成员变量是b,b的成员变量是a,导致两个智能指针的引用计数均为2,都等着对方结束,从而产生类似“死锁”的问题。因此,后续通过weak_ptr可以解决上述问题。

    6.通过weak_ptr解决shared_ptr循环引用

      weak_ptr类模板存储一个引向被shared_ptr管理的对象的若引用,weak_ptr管理对象之后不会增加它的引用计数,由于weak_ptr没有重载->,*等操作符。因此不能直接操作它所管理的对象,则必须通过lock函数将weak_ptr转化为shared_ptr。同样地,weak_ptr也可以和标准库中的容器一起工作。

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    #include <boost/weak_ptr.hpp>
    struct A{
        A(){
            std::cout << "A::A()" << std::endl;
        }
        ~A(){
            std::cout << "A::~A()" << std::endl;
        }
        void f(){
            std::cout << "A::f()" << std::endl;
        }
    };
    int main(){
        boost::shared_ptr<int> sp(new int(128)); // 建议使用
        std::cout << ++(*sp) << std::endl;
        boost::shared_ptr<int> sp2(sp);
        std::cout << sp2.use_count() << std::endl; // 引用计数
    
        boost::weak_ptr<int> wp(sp2);
        std::cout << wp.use_count() << std::endl; // 2 weak_ptr弱引用,不占计数次数
        std::cout << *wp.lock() << std::endl; // lock() 将weak_ptr转换为shared_ptr
        boost::shared_ptr<A> ap(new A); // 建议使用
        ap->f();
        std::cout << " --------------- " << std::endl;
        return 0;
    }
    //输出
    129
    2
    2 // 2 weak_ptr弱引用,不占计数次数
    129
    A::A()
    A::f()
     ---------------
    A::~A()

      由于weak_ptr不占引用计数,因此对于(5)产生的引用计数问题,则可以直接将class A中boost::shared_ptr<B> pb改为boost::weak_ptr<B> pb;则便可以完全析构。

    class A{
    public:
        A(){
            cout << "A()" << endl;
        }
        ~A(){
            cout << "~A()" << endl;
        }
        //boost::shared_ptr<B> pb;
        boost::weak_ptr<B> pb;
    };

    7.pimpl(private implemets)

       pimpl主要是为了隐藏类定义细节的一种手法。

    // 头文件 Example.h
    #ifndef EXAMPLE_H_
    #define EXAMPLE_H_
    #include <boost/shared_ptr.hpp>
    class Example {
    public:
        Example();
        Example(int x);
        int get_i();
    private:
        // int i;  // 隐藏变量i
        class implementation;
        boost::shared_ptr<implementation> _imp;
    };
    #endif /* EXAMPLE_H_ */
    // 实现文件 Example.cpp
    #include <iostream> #include "Example.h" class Example::implementation{ // 对类进行实现 public: int i; implementation(){ } ~implementation(){ std::cout << "~implementation()" << std::endl; } }; Example::Example():_imp(new implementation){ } Example::Example(int x): _imp(new implementation){ _imp->i = x; } int Example::get_i(){ return _imp->i; }
    // 测试文件 piplm_test.cpp
    #include <iostream>
    
    #include "Example.h"
    int main(){
        Example e(10);
        std::cout << e.get_i() << std::endl;
        return 0;
    }
    // 输出
    10
    ~implementation()
  • 相关阅读:
    解决Windows 7下IE11无法卸载、无法重新安装,提示安装了更新的IE版本
    [SQL Server] 数据库日志文件自动增长导致连接超时的分析
    DataTable转换为List<T>或者DataRow转换为T
    比较Js的substring、substr和C#的Substring
    .NET(c#)Parameters
    SheetJS保存Excel文件
    SheetJS将table转为Excel
    JS中使用let解决闭包
    Font Awesome图标的粗细
    滚动条样式修改
  • 原文地址:https://www.cnblogs.com/aizh/p/15749853.html
Copyright © 2011-2022 走看看