• OSG:先导篇 内存管理


    一.简介

    OSG提供了一种自动管理内存的机制,这种机制涉及到两个类:osg::ref_ptr类  和 osg::Referenced类

    二.osg::Reference类

     osg::Reference类实现了对内存区段的引用计数器功能。

    所有的OSG的节点和场景图形数据(状态信息 顶点数组 法线  纹理坐标)都派生于Referenced类进行内存引用计数

    Referenced类有3个主要组成部分:

    1.保护成员整型变量_refCount,用作引用计数,在构造时被初始化为0

    2.公有函数ref()和unref(),用于实现_refCount值得增加和减少,当_refCount为0时,unref()将自动释放该对象所占用的内存

    3.作为保护成员存在的虚析构函数

    1.类定义

    class OSG_EXPORT Referenced
    {
    public:
      Referenced();
      explicit Referenced(bool threadSafeRefUnref);
      Referenced(const Referenced&);
      inline Referenced& operator = (const Referenced&) {return *this;}
      virtual void setThreadSafeRefUnref(bool threadSafe);
    
    #if defined (_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
      bool getThreadSafeRefUnref() const {return true;}
    #else
      bool getThreadSafeRefUnref() const {return _refMutex != 0;}
    #endif
    
    #if defined (_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
      OpenThreads::Mutex* getRefMutex() const {return getGlobalReferencedMutex();}
    #else 
      OpenThreads::
    
    }

    三.osg::ref_ptr类

    osg::ref_ptr类用于实现一个指向Referenced对象的智能指针,并对其引用计数器进行管理

    osg::ref_ptr<>模板类包含了3个主要组成部分:

    1.一个私有指针_ptr,用于保存管理内存区域的地址,可以用get()方法返回_ptr的值

    2.类似指针重载定义了方法

    3.valid()方法,用于判断ref_ptr<>是否为空,不为NULL时返回true

     osg::ref_ptr<osg::类> 对象 = new osg::类;

     

    1.类定义

    template<class T>
    
    class ref_ptr
    {
    public:
    typedef T element_type;

    ref_ptr() : _ptr(0) {}
    ref_ptr(T* ptr) : _ptr(ptr) {if(_ptr) _ptr->ref();}
    ref_ptr(const ref_ptr& rp) : _ptr(rp.ptr) {if(_ptr) _ptr->ref();}
    template<class Other> ref_ptr(const ref_ptr<Other>& rp) : _ptr(rp._ptr) {if(_ptr) _ptr->ref();}
    ref_ptr(observer_ptr<T>& optr) : _ptr(0) {optr.lock(*this);}
    ~ref_ptr() {if(_ptr) _ptr->unref(); _ptr = 0;}

    ref_ptr& operator = (const ref_ptr& rp)
    {
    assign(rp);
    return *this;
    }

    template<class Other> ref_ptr& operator = (const ref_ptr<Other>& rp)
    {
    assign(rp);
    return *this;
    }

    inline ref_ptr& operator = (T* ptr)
    {
    if (_ptr==ptr) return *this;
    T* tmp_ptr = _ptr;
    _ptr = ptr;
    if (_ptr) _ptr->ref();
    if(tmp_ptr) tmp_ptr->unref();
    return *this;
    }

    #ifdef OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION
    operator T*() const {return _ptr;}
    #else

    bool operator == (const ref_ptr& rp) const {return (_ptr == rp._ptr);}
    bool operator == (const T* ptr) const {return (_ptr == ptr);}
    friend bool operator == (const T* ptr, const ref_ptr& rp) {return (ptr == rp.ptr)}

    bool operator != (const ref_ptr& rp) const {return (_ptr != rp._ptr);}
    bool operator != (const T* ptr) const {return (_ptr != ptr);}
    friend bool operator != (const T* ptr, const ref_ptr& rp) {return (ptr != rp._ptr);}

    bool operator < (const ref_ptr& rp) const {return (_ptr < rp._ptr);}

    private:
    typedef T* ref_ptr::*unspecified_bool _type;

    public:
    operator unspecified_bool_type() const {return valid() ? &ref_ptr::_ptr : 0;}
    #endif

    T& operator* () const {return *_ptr;}
    T* operator->() const {return _ptr;}

    //获取指针
    T* get() const {return _ptr;}

    bool operator !() const {return _ptr == 0;}
    bool valid() const {return _ptr != 0;}

    //返回指针
    T* release() {T* tmp = _ptr; if (_ptr) _ptr->unref_nodelete(); _ptr = 0; return tmp;}

    void swap(ref_ptr& rp) {T* tmp = _ptr; _ptr = rp._ptr; rp._ptr = tmp;}

    private:

    template<class Other> void assign(const ref_ptr<Other>& rp)
    {
    if (_ptr == rp._ptr) return;
    T* tmp_ptr = _ptr;
    _ptr = rp._ptr;
    if (_ptr) _ptr->ref();
    if (tmp_ptr) tmp_ptr->unref();
    }

    template<class Other> friend class ref_ptr;
    T* _ptr; };

    2.使用 osg::ref_ptr<>

    osg::ref_ptr<osg::Geode> geodePtr = new osg::Geode();
    osg::Geode* obj1 = * geodePtr;       //获取Geode指针
    osg::Geode* obj2 = geodePtr.get();  //获取Geode指针

    //作为返回值
    osg::Geode* createGeode()
    {
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    return geode.release();
    }

    四.使用智能指针

    在osg中,大多数场景图形类都继承自osg::Reference,但也有注意的地方

    1.使用智能指针模板的类必须继承自osg::Reference类,否则无法使用

    2.在创建智能指针之后,不能手动调动delete来删除该智能指针,否则编译会提示错误信息。因为osg::Reference的析构函数是保护类型

    3.在osg::Reference类成员函数中,有两个共有的成员函数ref() 和 unref(),它们主要是用来控制内存计数器,不要随意使用来改变内存计数器的值

    4.在osg中,可以new运算指针

    每个类要使用之前先用智能指针托管,用于避免内存泄漏

    bool CPickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
    {
    
      osg::ref_ptr<osg::Group> root = new osg::Group;
    osg::ref_ptr<osg::Geode> node1 = new osg::Geode;
    osg::ref_ptr<osg::Geometry> geo1 = new osg::Geometry;

    root->addChild(node1.get());
    node1->addDrawable(geo1.get());
    printf("%d, %d, %d", root->referenceCount(), node1->referenceCount(), geo1->referenceCount());
    }

    五.dynamic_cast

    dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换

    在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
    在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
  • 相关阅读:
    实时27实战机器学习:图片验证码识别(Java实现)
    大屏26深度学习模型来从文档图片中自动化地提取出关键信息成为一项亟待解决的挑战
    f-string想必作为Python3.6版本开始引入的特性,通过它我们可以更加方便地向字符串中嵌入自定义内容
    大屏25JAVA+selenium+tess4j识别登陆验证码截图与识别
    前端12 highcharts和echarts选择
    大屏20基于 Selenium 的 Web 自动化测试框架完美版自动化解决方案 [开源项目]
    大屏24字典python+selenium的行为
    大屏23Tesseract字库训练Tesseract 3
    大屏21解决数据问题python-tesseract-ocr的安装及使用
    大屏22解决数据问题java浏览器源.docx
  • 原文地址:https://www.cnblogs.com/k5bg/p/11451170.html
Copyright © 2020-2023  润新知