查看: 1960|回复: 17

为什么智能指针的地址用指针接受//有的情况内存错误,有的情况没事???

[复制链接]

该用户从未签到

发表于 2014-5-30 13:56:19 | 显示全部楼层 |阅读模式
本帖最后由 oirrm 于 2014-5-30 17:54 编辑

//内存错误
osg:: ref_ptr<osg::Texture2D> GrayTexture = new osg::Texture2D;
osg:: Texture2D* GrayImage = GrayTexture;
osg::ref_ptr<osg::StateSet> RectangleStateset = new osg::StateSet;
RectangleStateset->setTextureAttributeAndModes(0,GrayImage,osg::StateAttribute::ON);

//没有报错
osg::ref_ptr<osg::MatrixTransform> m_MT = new osg::MatrixTransform;
osg::Node pNode = m_MT;
osg::ref_ptr<osgUtil:: LineSegmentIntersector> intersector = new osgUtil:: LineSegmentIntersector(s, e);
osgUtil::IntersectionVisitor iv(intersector.get());
pNode->accept(iv);

该用户从未签到

发表于 2014-5-30 18:18:41 | 显示全部楼层
本帖最后由 cenfer 于 2014-6-2 21:18 编辑

//内存错误
osg:: ref_ptr<osg::Texture2D> GrayTexture = new osg::Texture2D;
osg:: Texture2D* GrayImage = GrayTexture;
osg::ref_ptr<osg::StateSet> RectangleStateset = new osg::StateSet;
RectangleStateset->setTextureAttributeAndModes(0,GrayImage,osg::StateAttribute::ON);


//试了下,编译没有内存错误

该用户从未签到

发表于 2014-5-30 18:25:25 | 显示全部楼层
本帖最后由 cenfer 于 2014-6-2 21:20 编辑

osg::ref_ptr<osg::StateSet> RectangleStateset = new osg::StateSet;
RectangleStateset->setTextureAttributeAndModes(0,new osg::Texture2D,osg::StateAttribute::ON);

//这样也没事阿

该用户从未签到

 楼主| 发表于 2014-5-31 23:21:10 | 显示全部楼层
cenfer 发表于 2014-5-30 18:25
非智能指针也不能作为智能指针的父节点。

osg:: Texture2D* GrayImage = new osg::Texture2D;
不使用只能指针如何去释放呢????

该用户从未签到

发表于 2014-6-1 08:00:28 | 显示全部楼层
本帖最后由 cenfer 于 2014-6-1 08:04 编辑

只要其父节点中有一个是智能指针就可以了,父节一释放,子节点会跟着一起释放的。
并不需要每一个指针对象都是智能指针

该用户从未签到

 楼主| 发表于 2014-6-2 13:54:13 | 显示全部楼层
本帖最后由 oirrm 于 2014-6-2 14:08 编辑
cenfer 发表于 2014-6-1 08:00
只要其父节点中有一个是智能指针就可以了,父节一释放,子节点会跟着一起释放的。
并不需要每一个指针对象 ...



//没有报错
osg::ref_ptr<osg::MatrixTransform> m_MT = new osg::MatrixTransform;
osg::Node* pNode = m_MT;  //为什么这个没有报访问冲突的错呢???
osg::ref_ptr<osgUtil:: LineSegmentIntersector> intersector = new osgUtil:: LineSegmentIntersector(s, e);
osgUtil::IntersectionVisitor iv(intersector.get());
pNode->accept(iv);

该用户从未签到

 楼主| 发表于 2014-6-3 10:53:18 | 显示全部楼层
cenfer 发表于 2014-5-30 18:25
osg::ref_ptr RectangleStateset = new osg::StateSet;
RectangleStateset->setTextureAttributeAndModes( ...

我也纳闷呢,之前也没问题。改了其它的无关代码就不行了
非智能指针与智能指针的地址可以互相赋值呢????

该用户从未签到

发表于 2014-6-3 13:51:33 | 显示全部楼层
不是可以相互赋值,是智能指针可以赋值给非智能指针
赋值运算可能是自动调用了.get()

该用户从未签到

发表于 2014-6-4 11:29:57 | 显示全部楼层
赋值操作会对计数器做相关操作,最好的方式还是多看源码实现辅助理解

该用户从未签到

 楼主| 发表于 2014-6-4 17:21:16 | 显示全部楼层
cenfer 发表于 2014-6-3 13:51
不是可以相互赋值,是智能指针可以赋值给非智能指针
赋值运算可能是自动调用了.get()

你不说用.release吗?

该用户从未签到

发表于 2014-6-4 20:11:33 | 显示全部楼层
这种情况下  我是用release的
osg::Node* fun()
{
osg::ref_ptr<osg::Node>  node = new osg::Node;
return node.release();
}

该用户从未签到

 楼主| 发表于 2014-6-5 14:22:16 | 显示全部楼层
本帖最后由 oirrm 于 2014-6-5 14:41 编辑
cenfer 发表于 2014-6-4 20:11
这种情况下  我是用release的
osg::Node* fun()
{


你的意思是当返回值返回的时候要用release?
而到参数传递没事》、???
osg::ref_ptr<osg::MatrixTransform> m_MT = new osg::MatrixTransform;
void fun(osg::Node pNode){
  //................

};
fun(m_MT); ????这样没事???

该用户从未签到

发表于 2014-6-5 16:28:15 | 显示全部楼层
oirrm 发表于 2014-6-5 14:22
你的意思是当返回值返回的时候要用release?
而到参数传递没事》、???
osg::ref_ptr m_MT = new o ...

我的意思是自己看下源码。

// implicit output conversion
operator T*() const { return _ptr; }

T* get() const { return _ptr; }

T* release() { T* tmp=_ptr; if (_ptr) _ptr->unref_nodelete(); _ptr=0; return tmp; }

T* _ptr;


  /** Decrement the reference count by one, indicating that
            a pointer to this object is referencing it.  However, do
            not delete it, even if ref count goes to 0.  Warning, unref_nodelete()
            should only be called if the user knows exactly who will
            be responsible for, one should prefer unref() over unref_nodelete()
            as the latter can lead to memory leaks.*/
        int unref_nodelete() const;

       

该用户从未签到

 楼主| 发表于 2014-6-5 16:57:44 | 显示全部楼层
cenfer 发表于 2014-6-5 16:28
我的意思是自己看下源码。

// implicit output conversion

为什么当函数参数传递没事???
osg::ref_ptr<osg::MatrixTransform> m_MT = new osg::MatrixTransform;
void fun(osg::Node pNode){
  //................
};
fun(m_MT); ????这样没事???

该用户从未签到

发表于 2014-6-5 19:27:21 | 显示全部楼层
本帖最后由 cenfer 于 2014-6-5 19:30 编辑

不是让你看源码吗
下面的是不是对类型转换的重载
// implicit output conversion ---隐式转换输出
operator T*() const { return _ptr; }  //实现和get方法相同

传递实参与形参类型不一致显然要进行类型转换
本人能力有限,不确定以上是不是类型转换的重载。

不过 实践已证明 那样类型转换确实正确进行了。

该用户从未签到

 楼主| 发表于 2014-6-6 10:51:44 | 显示全部楼层
cenfer 发表于 2014-6-5 19:27
不是让你看源码吗
下面的是不是对类型转换的重载
// implicit output conversion ---隐式转换输出


osg::Texture2D GrayTexture = new osg::Texture2D;//我想释放GrayTexture 调用delete???还是啥呢有函数释放吗?

该用户从未签到

 楼主| 发表于 2014-6-9 09:42:55 | 显示全部楼层
cenfer 发表于 2014-6-4 20:11
这种情况下  我是用release的
osg::Node* fun()
{

使用release之后,如何释放内存呢???
osg::Node* fun()
{
osg::ref_ptr<osg::Node>  node = new osg::Node;
return node.release();
}

该用户从未签到

发表于 2014-6-9 22:02:19 | 显示全部楼层
本帖最后由 cenfer 于 2014-6-9 23:19 编辑
oirrm 发表于 2014-6-9 09:42
使用release之后,如何释放内存呢???
osg::Node* fun()
{


osg::Referenced 的子类一般不需要考虑释放问题,也无法直接手动释放。

1. 场景一般都是树结构,只要保证根节点是智能指针就可以了。其它树杈、树枝、树叶节点不一定非要声明或定义为智能指针。
用osg::Group的源码解释下这个问题:
Group类是构建场景树的基本类,成员变量NodeList _children存放子树。
再看一下NodeList是什么:typedef std::vector< ref_ptr<Node> > NodeList。
若果够聪明,从这里一定可以看出:即使一个子节点不定义为智能指针,addChild之后也会被智能指针引用。
所以只要保证根节点被智能引用,就能保证其子节点的智能释放。
说白了,就是构建树的同时也构建了一个智能引用的树,一旦树根智能释放,会引发子树连锁反应。
(以上只是个人见解,不一定正确)

2.release()返回引用对象,同时引用计数归0,但不释放引用对象。
如果这样写:osg::Node* fun(){osg::ref_ptr<osg::Node>  node = new osg::Node;return node;}
函数返回时ref_ptr对象的生命周期结束,析构,引用对象被自动释放。release()取消了自动释放,并将引用对象返回。

3.像osg::Node* fun()只是创建一个场景节点,要想加入场景必然使用addChild之类的方法。
若果非要这样用main(){osg::Node* node = fun();}
我只能说内存泄露是活该的!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表