create出来的对象,什么时候需要retain?

用create创建同样一个对象的代码,有时候需要retain,有时候不需要。我现在只能在运行出错时,再给它加上retain. 不运行一下,完全不知道此处应不应该retain.
create出来的对象都带有autorelease.

以下测试代码: 看注释部分。(GameDialog继承Ref,也跟其他cocos2d类一样是用create创建)

bool GameDialog::init()
{
    _richText = cocos2d::ui::RichText::create();
    if (nullptr==_richText)
    {
        return false;
    }
    CC_SAFE_RETAIN(_richText); //这两个地方不retain会出错!,若在场景中直接创建richbox是不需要retain的

    _layer = cocos2d::LayerColor::create(cocos2d::Color4B(0, 0, 0, 0));
    if (nullptr == _layer)
    {
        return false;
    }
    CC_SAFE_RETAIN(_layer);


    _bgImg = cocos2d::Sprite::create(U8("pictures/dialog_bg1.png"));//这里创建sprite怎么就不需要retain了?
    _charImg = cocos2d::Sprite::create(U8("heads/小红.png"));            //也不需要retain
    if (nullptr==_bgImg||nullptr==_charImg)
    {
        return false;
    }
    _layer->addChild(_bgImg, 1);
    _bgImg->addChild(_richText, 1);
    _bgImg->addChild(_charImg, -1);

    auto director = Director::getInstance();
    auto winSize = director->getWinSize();
    _bgImg->setAnchorPoint(Vec2(0.5f, 0.0f));
    _bgImg->setPosition(winSize.width / 2, 0.0f);
    _charImg->setAnchorPoint(Vec2::ZERO);
    _charImg->setPosition(0, _bgImg->getContentSize().height-50);
    _richText->setAnchorPoint(Vec2(0.5f, 1.0f));
    _richText->setPosition(Vec2(_bgImg->getContentSize().width / 2, _bgImg->getContentSize().height - 50-10));
    
    _richText->ignoreContentAdaptWithSize(false);
    _richText->setContentSize(Size(_bgImg->getContentSize().width / 2, 0));

    std::string txt = U8("小明,出去玩吗?");
    RichElementText* re_txt = RichElementText::create(1, Color3B::WHITE, 255, txt, U8("fonts/汉仪小隶书简.ttf"), 20);
    _richText->pushBackElement(re_txt);    

}


```

不加retain哪里会出错?

不知道是哪里啊。我就在一个地方用到这类对象:

这个测试代码,在空场景的init中。

    auto dlg = RPG::GameDialog::create();
    this->addChild(dlg->_layer, 3);


```

在引用该对象之前如果该对象被释放了那就需要retain一下吧

你这个GameDialog是继承哪个类的
似乎没有调用父类的init哦

直接继承Ref. Ref没init()吧? 自己实现create 带autorelease

今天不知道改了什么了。把那2个retain去掉相应的把析构中的release去掉,程序又不会崩溃了。汗~
哎,去把引用计数理一下,看看搞什么鬼。
虽然是测试,代码随便了些。但使用方式有问题,埋下地雷:3:

用了内存自动管理。得明白一件事:创建出来的对象,过了一帧之后还存不存在。:10:我勒个去
要是忘记了一个增加计数的方法,就有地雷了:3:
要是手动增加计数了,那会在哪释放了,这就跟自己new一样了吧?:15:

你这一坨东西的根节点应该是_bgImg这个东西
如果_bgImg没有父节点add它的话,_bgImg和其子节点会在该帧即将结束时被回收
和你这个GameDialog完全没关系,说到底你这个GameDialog类存在的意义是什么,搞不懂。

这只是测试代码,看看效果。接口都还没做。 最后使用的时候 GameDialog也许会做成全局对象或单例。反正一个游戏只有一种风格与npc对话方式
这一坨东西的根节点是_layer.
也就是说,在场景测试代码里,GameDialog死了,但成员_layer还在:890:

GameDialog和成员_layer并没有生存销毁的依赖关系
_layer retain一下可以保证加载_layer的子孙节点都安全

引用计数问题归根结底还是内存管理问题。在引用计数机制下,谁要使用这个对象谁就要在使用前retain,使用完release,确保在自己的生命周期内正确维护该对象属于自己管理的reference,而AutoReleasePool的作用就是在每帧检查其管理的ref,如果该ref的引用计数为1,即只有自己持有该ref,则delete之。这样的好处是当用户new一个node并调用autorelease,把node的引用计数管理交给AutoReleasePool,用户就不用管这个对象什么时候释放了,当node的ref变为1时AutoReleasePool会自行释放他,使得用户从繁琐的对象管理中抽身,将更多精力放在逻辑和效果实现上。

ok… :7:

就是这种想法会混淆内存自动管理机制。以为用的脚本语言的那种自动回收呢。但实际上,莫名其妙就崩溃了。
还是要知道对象什么时候释放才好。ref变为1时,不是pool把对象释放了。是对象自己释放了。pool只是把它们减1一次。(这种说法有没对?)

等以后再写代码时,看还会不会出现那种出我意料之外的崩溃。到时再验证下。

这么说是对的,我之前的说法有问题,在Ref的实现中当reference=1时会调用delete this。
简单的说,如果你create一个对象并且要自己管理它的时候,就retain,如果只是create出来放到其他节点上,就不retain

一般不需要,有时候你想反复利用一个对象,retain后你就可以反复addchild、removechild而不会删除对象,即方便效率也高,析构函数里再release掉即可

就是创建出来如果不马上添加到节点树中的对象需要保留,不然会被自动释放,就是这么个套路,没那么复杂