游戏开发论坛

 找回密码
 立即注册
搜索
12
返回列表 发新帖
楼主: instemast

敬请兄弟们帮忙斟酌-关于AddRef与函数返回指针

[复制链接]

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-5-9 18:23:00 | 显示全部楼层

Re:敬请兄弟们帮忙斟酌-关于AddRef与函数返回指针

还有一个有意思的问题是,
构造函数里(new的时候)m_RefCount是 0 还是 1 的问题。而且这个和循环引用也有关连。

《游戏编程全接触》里面说开始==0。
恩,这样对于SmartPtr封装来说比较方便。
(函数返回的时候不AddRef)

但是,在你AddRef之前,比如在Constuctor内部,
如果有this->AddRef和this->Release的地方。。。
比如说内部的另一个对象引用了this,然后又释放了。。。
这将导致Release()检查引用计数,然后,我们的对象还没有
初始化完成就被删除了。。。


m_RefCount初始值=1,看似可以解决这个问题,其实不然,
(而且m_RefCount初始值=1,编写SmartPtr不方便)

在constructor中其他对象对this的AddRef和Release,这说明什么?
----循环引用,直接被逮捕了~~循环引用被扼杀在摇篮里了!!

实际上不管m_RefCount的初始值为多少,都不行。我们的问题和m_RefCount初始值无关!

这的确非常有趣不是吗?
因为你不会在构造器里写“this->AddRef/Release”之类的代码。
所以,在构造阶段的this指针的引用计数的改变,说明:循环强引用。


就是说,你只有用weak ptr或者gc~~

既然m_RefCount的初始值无所谓,那么我们轻松一点(作者Mike是对的!),
m_RefCount初始值=0。

-------------------------------------
我如何解决C++的这种问题:

我发现几乎只有 UI 需要对象间的相互耦合,
所以,我将Only针对UI类库解决这个问题。

上面的帖子里已经解决了!不是吗?(控件,容器之间用weak ptr)

那么,我的心灵,已经得到安慰。。。

也不需要gc, 也不需要在RootClass中加入解耦和虚函数

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
 楼主| 发表于 2008-5-9 20:18:00 | 显示全部楼层

Re:敬请兄弟们帮忙斟酌-关于AddRef与函数返回指针

有人说:lz不会用单方面耦合的阿?
----实际上,以前RpgDIY里我就是这么做的。C++起初也是这么做的。

后来觉得,这么做违背了“对称的美”。而且思维纠缠。这不高深,看伪代码:

Parent::AddChild(child);
Parent::RemoveChild(child);
Child::SetParent(parent);

AddChild和RemoveChild里面应该做什么?SetParent里面做什么?
我曾经这么做的:

AddChild(child)
{
     child->SetParent(parent);
}
RemoveChild正好相反,child->SetParent(null);

而SetParent里面我什么额外操作都没有做~~

---------------------------------------------------------

有人说,应该自动相互处理,SetParent也会调用AddChild。
----我从未试过----这需要间接递归标志变量。

---------------------------------------------------------

目前的做法是,清爽的做法----AddChild/ RemoveChild/ SetParent
里面不做任何 额外的 操作。

父子的耦合,由用户(第三者)完成。这很简洁,很对称。

===================================================================

打断下,我们看一下C++指针。如果采用现在的做法(对称的方法),
我们没有理由使用 强引用(AddRef),这不对称。
也似乎不应该在destructor中相互解耦----交给用户(第三者)把。
----因为,耦合是用户干的,解耦也交给他算了

---------------------------------------------------------------

还有种做法(我不喜欢)----不对称做法----就是我以前的做法,
SetParent()作为private成员,Parent是friend.
这样,对于用户来说,! 看 不 见 !SetParent.也不知道Child中含有parent的指针。

Add/Remove Child()的时候:
child->m_pParent->RemoveChild(child);
child->m_pParent=this;     // 弱 引用
this->m_List->add( SmartPtr<Child>(child) );      // 强 引用
Parent::~Parent(){ RemoveAllChildren(); }

(Child::~Child()不做处理~~~)

这样,很安全,可以说,从外部来看,耦合关系,由Parent全权处理。
(你能够调用private方法吗?)

这样,Child::m_pParent 这个 weak ptr 的“有效期”被嵌套在 Parent的 生命期 之中!
而另一方面,Parent::m_List由于是 SmartPtr,所以,随便你怎么删除children~~
不管你怎么玩,都安全!---- 不 对 称 , 就 要 彻 底 不 对 称 。

---------------------------------------------------------------

还有个方法,就是对称 + 保姆式代码(自动为你耦合解耦,服务一切)
估计我不想尝试这种方法。(注意!不能用SmartPtr,那么干脆都不要用吧)

AddChild, RemoveChild, SetParent, ~Parent, ~Child
这里头会,自动解耦,自动重新耦合。

还有,龌龊的间接递归标志... ...我应该不会用这种方法。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-22 13:55

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表