那些年你不知道的C/C++陷阱与套路…

摘要: 本文结合作者的工作经验和学习心得,对C++语言的一些高级特性,做了简单介绍;对一些常见的误解,做了解释澄清;对比较容易犯错的地方,做了归纳总结;希望借此能增进大家对C++语言了解,减少编程出错,提升工作效率。

一、导语

  C++是一门被广泛使用的系统级编程语言,更是高性能后端标准开发语言;C++虽功能强大,灵活巧妙,但却属于易学难精的专家型语言,不仅新手难以驾驭,就是老司机也容易掉进各种陷阱。

        本文结合作者的工作经验和学习心得,对C++语言的一些高级特性,做了简单介绍;对一些常见的误解,做了解释澄清;对比较容易犯错的地方,做了归纳总结;希望借此能增进大家对C++语言了解,减少编程出错,提升工作效率。

二、陷阱

我的程序里用了全局变量,为何进程退出会莫名其妙的core掉?

        Rule:C++在不同模块(源文件)里定义的全局变量,不保证构造顺序;但保证在同一模块(源文件)里定义的全局变量,按定义的先后顺序构造,按定义的相反次序析构。

        我们程序在a.cpp里定义了依次全局变量X和Y;

        按照规则:X先构造,Y后构造;进程停止执行的时候,Y先析构,X后析构;但如果X的析构依赖于Y,那么core的事情就有可能发生。

        结论:如果全局变量有依赖关系,那么就把它们放在同一个源文件定义,且按正确的顺序定义,确保依赖关系正确,而不是定义在不同源文件;对于系统中的单件,单件依赖也要注意这个问题。

 std::sort()的比较函数有很强的约束,不能乱来

        相信工作5年以上至少50%的C/C++程序员都被它坑过,我已经听到过了无数个悲伤的故事,《圣斗士星矢》,《仙剑》,还有别人家的项目《天天爱消除》,都有人掉坑,程序运行几天莫名奇妙的Crash掉,一脸懵逼。

        如果要用,要自己提供比较函数或者函数对象,一定搞清楚什么叫“严格弱排序”,一定要满足以下3个特性:

        ●非自反性

        ●非对称性

        ●传递性

        尽量对索引或者指针sort,而不是针对对象本身,因为如果对象比较大,交换(复制)对象比交换指针或索引更耗费。

注意操作符短路

        考虑游戏玩家回血回蓝(魔法)刷新给客户端的逻辑。玩家每3秒回一点血,玩家每5秒回一点蓝,回蓝回血共用一个协议通知客户端,也就是说只要有回血或者回蓝就要把新的血量和魔法值通知客户端。

        玩家的心跳函数heartbeat()在主逻辑线程被循环调用

void GamePlayer::Heartbeat()

{

    if (GenHP() || GenMP())

    {

        NotifyClientHPMP();

    }

}

        如果GenHP回血了,就返回true,否则false;不一定每次调用GenHP都会回血,取决于是否达到3秒间隔。

        如果GenMP回蓝了,就返回true,否则false;不一定每次调用GenMP都会回血,取决于是否达到5秒间隔。

        实际运行发现回血回蓝逻辑不对,Word麻,原来是操作符短路了,如果GenHP()返回true了,那GenMP()就不会被调用,就有可能失去回蓝的机会。你需要修改程序如下:

void GamePlayer::Heartbeat()

{

    bool hp = GenHP();

    bool mp = GenMP();

    if (hp || mp)

    { 

        NotifyClientHPMP();

    } 

}

        逻辑与(&&)跟逻辑或(||)有同样的问题, if (a && b) 如果a的表达式求值为false,b表达式也不会被计算。

        有时候,我们会写出 if (ptr != nullptr && ptr->Do())这样的代码,这正是利用了操作符短路的语法特征。

别让循环停不下来

for (unsigned int i = 5; i >=0; --i)

{

    //...

}

        程序跑到这,WTF?根本停不下来啊?问题很简单,unsigned永远>=0,是不是心中一万只马奔腾?

        解决这个问题很简单,但是有时候这一类的错误却没这么明显࿰

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值