摘自:Don Burns《Using Reference Pointers in Producer and OpenSceneGraph》 ref_ptr<> 利用引用计数管理分配在堆上的内存,计数为(0)时自动释放内存 规则1: ================================== 首先弄清楚: 1、分配在堆(heap)上的内存是指调用 new() 或者 malloc() 之类的方法动态分配的那些,需要由程序员自己负责跟踪和回收(delete、free),否则会引起内存泄漏;分配在栈(stack)上的内存由编译器管理,不用我们操心,比如局部变量。 2、引用计数(reference count)是用来管理分配在堆上的对象的。若有个外部实体需要用到这个对象,引用计数+1,用完则-1,当减为0时对象就释放它自己。 =============================== 下面看 ref_ptr<>: ref_ptr<>是模版类,可以实例化为指向任何从Referenced继承的对象指针。严格地说,ref_ptr<>自身是分配在栈上的,但是保存的是分配在堆上的内存的地址。它的作用就是实现自动引用计数:ref_ptr<>所指对象的引用计数在复制构造函数或者"="操作符时 +1,在析构函数里 -1。 现在比较一下: void SomeClass::someMethod() 上面的函数返回时,nodeRefPtr 调用其析构函数,对象的引用计数减为(0),对象自动释放它自己;而nodePtr 在函数外无效,它原来指向的内存仍然留在堆里,而且无法跟踪。 再看这个例子: void SomeClass::someMethod(osg::Group *group) 函数中group的ref_ptr<>使对象的引用计数增为(2),当函数返回时,nodeRefPtr 析构使对象的计数减为(1),所以当group还在使用此对象时它不会释放自己。对于.get(),暂时可以理解为返回osg::Node对象的地址。 一般用 bool valid() 来判断智能指针是否指向有效的地址。 ============================= 需要注意的几点: 1、混用 * 和 ref_ptr<> 看下面这段代码,doSomethingWithNode 函数利用ref_ptr<>将对象的引用计数增为(1),函数返回时又减为(0),此时对象释放自己占用的内存。当doSomeStuff()再对那块内存操作时就会出错。 void SomeClass::doSomethingWithNode( osg::Node *node ) 规则1: --------------------------------- 2、用ref_ptr<> 作函数返回值 下面的代码中,createANode()动态分配的内存在它退出时就已经释放,initializeOrSomething()无法在释放之前增加引用计数。 void SomeClass::initializeOrSomething() 有两个方法解决: 所以最好还是将ref_ptr<>作为返回值: osg::ref_ptr SomeClass::createANode() 规则2: --------------------------------- 3、不适当地应用从Referenced 继承的对象 osg 和Producer 的基类把它们的析构函数定义为protected,强制用户将这些类分配在堆上而不是栈上。但是,下面定义的MyNode 却是合法的,它的析构函数设为public。这样程序员可以合法(但是不适当)地将这个类作为局部变量放在栈上,这时如果有个ref_ptr<> 引用它,就会使引用计数减为(0),导致栈变量试图删除它自己。 class MyNode : public osg::Node 规则4: --------------------------------- 4、循环引用 当两个从Referenced 继承的类实例互相引用对方时,就可能造成循环引用。 class B; class A : public osg::Referenced class B : public osg::Referenced void A::setB( B *b) { _b=b; } int main() 解决方法是利用简单指针: class B; class A : public osg::Referenced class B : public osg::Referenced void A::setB( B *b) { _b=b; } int main() 规则5(规则1的例外): |
osg学习一:Access violation 错误的解决
最新推荐文章于 2023-09-15 20:31:48 发布
2011-04-07 21:43