do{}while(0)与CC_BREAK_IF的绝妙搭配

转自https://blog.csdn.net/cnmm22/article/details/46621169

从一开始觉得没有必要,到觉得非常好用,我经历了大概两个月的时间,下面来总结一下什么情况下使用这种结构吧。

第一种情况:当加载文件的时候,如果加载文件失败,需要报错的时候。

当前,可以用try{}catch(){}finally{}这种结构,但是这样做会极大的增加编译后文件的大小,使用do{}while(0)加上CC_BREAK_IF就能实现一样的效果,而且不增加文件的大小。

下面是一个例子:

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

bool GameScene::setScene()

{

    do{

        auto node = SceneReader::getInstance()->createNodeWithSceneFile("publish/GameScene.csb"); 

        CC_BREAK_IF(!node);

        m_UI_Background->addChild(node);

 

        auto Checkerboard = (ComRender*)(node->getChildByTag(10009)->getComponent("GUIComponent"));

        CheckerboardUI = Checkerboard->getNode();

        //设置按钮

        m_btn_Setting = dynamic_cast<button*>(CheckerboardUI->getChildByName("Button_Setting"));

        CC_BREAK_IF(!m_btn_Setting);

        //音乐按钮

        m_btn_Music = dynamic_cast<button*>(CheckerboardUI->getChildByName("Button_Music"));

        CC_BREAK_IF(!m_btn_Music);

        //棋盘锁

        m_btn_Lock = dynamic_cast<button*>(CheckerboardUI->getChildByName("Button_Lock"));

        CC_BREAK_IF(!m_btn_Lock);

        //棋盘图片

        m_Image_Checkerboard = dynamic_cast<imageview*>(CheckerboardUI->getChildByName("Image_Checkerboard"));

        CC_BREAK_IF(!m_Image_Checkerboard);

        m_Checkerboard = Checkerboard::create(m_Image_Checkerboard);

        auto SelectPeople = (ComRender*)(node->getChildByTag(10031)->getComponent("GUIComponent"));

        SelectPeopleUI = SelectPeople->getNode();

        this->setCampBtn();

 

        return true;

    }while(0);

    CCLOG("ERROR:Load Resources Fail in GameScene::setScene");

    return false;

}</imageview*></button*></button*></button*>


如果在中途出现任何一个变量执行后还是nullptr,那么就CC_BREAK_IF,然后显示错误日志,最后返回false给上层函数进行处理。这样的处理方式是不是既优雅又方便快速,又避免了可能错误使用空指针。

 

 

第二种情况:当无论如何都需要在函数最后进行清理操作的时候。

下面举一个比较典型的例子,就是在函数开头声明了一个new的指针(非智能指针),按照正常的流程,需要delete,但是我们无法保证程序会不会在中途就return了,因为后续的维护者并不知道还有这个清除操作需要执行,下面是一个对比例子:

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

//error

void test()

{

    GameScene* gamescene = new GameScene;

    // doSomething...

    if(gamescene->getChildByTag(111) == nullptr)

    {

        return;

    }

    // doSomething...

    delete gamescene;

    gamescene = nullptr;

}

 

//right

void test1()

{

    GameScene* gamescene = new GameScene;

    do{

        // doSomething...

        CC_BREAK_IF(gamescene->getChildByTag(111) == nullptr);

        // doSomething...

    }while(0);

    delete gamescene;

    gamescene = nullptr;

}


使用CC_BREAK_IF可以保证永远都会执行到最后两行,也就不会出现内存泄露。

 

 

但是这个组合也不是万能的,下面就说一个不适合这种结构的情况吧。当do{}while(0)的括号中存在循环的时候,就不适用这个组合了,因为break毕竟只能跳出一层循环,下面是一个例子:

 

?

1

2

3

4

5

6

7

8

9

10

11

12

void test2()

{

    do{

        for(int i = 0;i <5;++i)

        {

            // doSomething...

            CC_BREAK_IF(i>4);

            // doSomething...

        }

        CCLOG("永远显示这一行日志");

    }while(0);

}


我们希望的是,CC_BREAK_IF能跳出do{}while(0)循环,但是实际上,只跳出了for循环,所以使用do{}while(0)和CC_BREAK_IF的时候,需要确保其内部不能存在其他循环,如果存在循环,还是建议使用try{}catch(){}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值