OSG中的智能指针

OSG中使用了智能指针,对堆内存进行管理。 

智能指针,其实就是在原始指针的基础上,加上了一个引用计数,然后通过引用计数的值,来决定什么时候释放内存。其目标就是确保一段内存会被释放,且只被释放一次。


OSG中的引用计数,存放在osg::Referenced类中,然后这个类提供了对引用计数进行增加的函数Referenced::ref(), 以及对引用计数进行减少的函数Referenced::unref()。这个类只提供了引用计数的基本操作。所有继承自osg::Referenced的类,它里面都有一个引用计数。


但是什么时候增加引用计数,什么时候减少引用计数,则是通过ref_ptr来进行管理的。当一个内存块被new出来之后,只要它将这个内存块指针交给ref_ptr进行管理,程序就不需要考虑什么时候释放这个内存块了。


下面的代码存在问题,在root->removeChild的时候,cow这个内存块已经被释放了。此时再把cow加到场景中,问题就出来了,因为这个内存已经被释放了。

#include <osg/ref_ptr>
#include<osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Node>


int main(int argc, char **argv)
{
	osgViewer::Viewer viewer;

	osg::Node *cow = osgDB::readNodeFile("cow.osg");
	osg::Group *root = new osg::Group;
	root->addChild(cow);
	root->removeChild(cow);
	viewer.setSceneData(cow);

	return viewer.run();
}


但是如果readNodeFile返回的内存,交给ref_ptr进行管理,则不会出现问题,如下所示。

#include <osg/ref_ptr>
#include<osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Node>

int main(int argc, char **argv)
{
	osgViewer::Viewer viewer;

	osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");
	osg::Group *root = new osg::Group;
	root->addChild(cow);
	root->removeChild(cow);
	viewer.setSceneData(cow);

	return viewer.run();
}

所以在OSG中,只管new对象,new完之后,交给ref_ptr进行管理即可。所有继承自Referenced的类,都支持ref_ptr进行管理,因为它们自身都有一个引用计数。


但是有一点例外,如果是通过函数创建对象,创建完了之后,需要返回该对象的内存,在函数内部,则不应该把这个内存交给智能指针去管。比如

#include <osg/ref_ptr>
#include<osgViewer/Viewer>
#include <osgDB/ReadFile>

osg::Node* createCowNode()
{
	osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");
	return cow.get();
}

int main(int argc, char **argv)
{
	osgViewer::Viewer viewer;
	viewer.setSceneData(createCowNode());
	return viewer.run();
}
上面的代码存在问题,因为智能指针cow以为你离开createCowNode之后,就不需要这个cow所指的内存,它把这块内存给删了,所以导致程序访问出错。

这块内存虽然交给了智能指针处理,但是它的处理方式与我们想象的不一样。这个和返回局部对象的指针那种情况一样了。

正确的做法是函数返回之后,再对内存使用智能指针进行管理,像下面这样

#include <osg/ref_ptr>
#include<osgViewer/Viewer>
#include <osgDB/ReadFile>

osg::Node* createCowNode()
{
	return osgDB::readNodeFile("cow.osg");
}

int main(int argc, char **argv)
{
	osgViewer::Viewer viewer;
	osg::ref_ptr<osg::Node> cow = createCowNode();
	viewer.setSceneData(cow.get());
	return viewer.run();
}

综上所述,创建的内存块,交给智能指针进行管理,也还是需要考虑智能指针它本身的作用域和生命周期。因为智能指针它自己本身是位于栈上的,它管理的内存块位于堆上。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值