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来管理对象了),如果移交不慎(接受者在不使用对象时不进行释放),就会造成内存泄漏。