osg的ref_ptr和observer_ptr

ref_ptr就是所谓的强指针类型

observer_ptr是所谓的弱指针类型

需要注意的是他们都是类,而不是指针,只不过他们用于管理指针。

1.如何实现自动内存管理

所谓自动内存管理就是只管对象或指针的创建和使用而不管销毁。

实现自动内存管理指的是ref_ptr,他工作的机理就是每当多引用一次对象(比如addChild)其引用计数就会增加1,多删除一次对象(removeChild)其引用计数就会减1,如果引用计数为0,则销毁对象。

另外定义其对象实例会有生命周期,在对象实例超出生命周期进行销毁时会自动释放所管理的指针,因而实现内存管理,如下代码:

class AAA:public osg::Referenced{

};

int
main(int argc, char** argv)
{
    {
        osg::ref_ptr hhh=new AAA();//超出其生命周期时会自动释放AAA指针,从而实现内存管理
    }
    
}

以下使用ref_ptr的方式不推荐使用(虽然也能进行内存管理,不会出现内存泄漏),容易出现不可预期的问题(指针所指向内存已经删除,但是指针并未置NULL,导致再次使用指针时出现不可预期问题)

class AAA:public osg::Referenced{

};

int
main(int argc, char** argv)
{
    AAA* tt=new AAA;
    {
        osg::ref_ptr st=tt;
    }//已经删除了内存,但是tt并未置NULL,再次访问tt中的成员函数、成员变量会出现不可预期问题
    
}

下面的代码也很有误导性

class AAA:public osg::Referenced{

};

int
main(int argc, char** argv)
{
    AAA* tt=new AAA;
    osg::ref_ptr st=tt;
    delete tt;
    if(st.valid()){
        std::cout<<"valid";//st的输出结果时valid
    }else{
        std::cout<<"invalid";
    }
    
}
class AAA:public osg::Referenced{

};

int
main(int argc, char** argv)
{
    AAA* tt;
    osg::ref_ptr st;
    {
        tt=new AAA;
        st=tt;
    }

    delete tt;
    tt=0;
    if(st.valid()){
        std::cout<<"valid";//仍是valid
    }else{
        std::cout<<"invalid";
    }
    
}

如果ref_ptr指向了其它对象,那么它原理管理的对象计数会减1。

2.管理的对象有所区别

ref_ptr会用引用计数器管理同一个对象,避免重复拷贝占用内存。observer_ptr会采用观察者模式管理对象,不会干扰对象的创建和销毁。

ref_ptr、observer_ptr管理的只能是继承自osg::Referenced的对象。比如下面代码会报错:

class AAA{

};

int
main(int argc, char** argv)
{
    osg::ref_ptr hhh=new AAA();//error: C2039: “unref”: 不是“AAA”的成员
    osg::observer_ptr ohhh(hhh);// error: C2039: “getOrCreateObserverSet”: 不是“AAA”的成员
}

将AAA改成继承自osg::Referenced则没有问题。

class AAA:public osg::Referenced{

};

int
main(int argc, char** argv)
{
    osg::ref_ptr hhh=new AAA();
    osg::observer_ptr ohhh(hhh);
}

3.内存泄漏就一去不复返了吗

需要注意的是,使用ref_ptr并不能避免内存泄漏,因为其有release函数,将对象的管理权移交(很有可能不再采用ref_ptr来管理对象了),如果移交不慎(接受者在不使用对象时不进行释放),就会造成内存泄漏。

 

 

你可能感兴趣的:(osg,C++)