
OSG学习:OSG中的智能指针
但是如果readNodeFile返回的内存,交给ref_ptr进行管理,则不会出现问题,如下所示。
所以在OSG中,只管new对象,new完之后,交给ref_ptr进行管理即可。所有继承自Referenced的类,都支持ref_ptr进行管理,因为它们自身都有一个引用计数。
上面的代码存在问题,因为智能指针cow以为你离开createCowNode之后,就不需要这个cow所指的内存,它把这块内存给删了,所以导致程序访问出错。
综上所述,创建的内存块,交给智能指针进行管理,也还是需要考虑智能指针它本身的作用域和生命周期。因为智能指针它自己本身是位于栈上的,它管理的内存块位于堆上。
发布日期:2025-05-01 06:15:15
浏览次数:2
分类:技术文章
本文共 2213 字,大约阅读时间需要 7 分钟。
转载自:
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();
- }
- #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();
- }
这块内存虽然交给了智能指针处理,但是它的处理方式与我们想象的不一样。这个和返回局部对象的指针那种情况一样了。
正确的做法是函数返回之后,再对内存使用智能指针进行管理,像下面这样
- #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();
- }
综上所述,创建的内存块,交给智能指针进行管理,也还是需要考虑智能指针它本身的作用域和生命周期。因为智能指针它自己本身是位于栈上的,它管理的内存块位于堆上。
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年04月23日 14时38分01秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!