从语法糖想到的
05 Jan 2013 by LelouchHe
遭遇
今天写C++程序的时候在一个很弱的地方翻船了—引用.我初始化引用为一个量,接着为了省事,就赋值为另一个,然后又一个,到了最后,发现所有的值都变了.
一开始我还以为是库的问题(因为刚遇到一个库的bug),但仔细看过之后,猛然发现是引用诶,结果我用的和普通变量一样,修改引用等于修改被引用的对象诶.
我真是猪头,明明是我自己修改了变量的值,还在这里埋怨库
但是
本质来讲,引用和指针是一个层面上的东西,不过指针更低,引用稍微安全了一点,但归根结底,引用可以看作是指针的语法糖而已,省却了我们很多的解引用操作.
可是从我的这次弱爆了的经历来看,这种语法糖究竟是好还是不好呢?
如果
假设我使用的是原始的指针,我肯定不会犯这样的错误,因为我每次的使用肯定会解引用,而且大大的*
会提示我修改的究竟是指针还是被指之物
反思
我以前一直觉得引用是个好的语法糖,不用每次都烦人的写上*
,而且我一直自认为自己不会犯这样的低级错误.
我当然能分的清引用和引用之物,指针和指针之物,但是我还是犯了,这说明一个问题,也就是错误是普遍的,人都会犯错误的,明确的语法能拯救一个错误不至于过于糟糕,但含混不清的语法糖却把bug深深的埋入了简洁的表达中
如果我写的是指针,编译器肯定就不会通过我的代码,我肯定也第一时间知道我错了(而且我肯定不会这么用指针的)
不只是引用这种初级的语法糖,很多东西都是类似的.
比如操作符重载,以前我超级喜欢这个,觉得像Java这种没有操作符重载的都很烂,但是在开发一种使用jsoncpp的服务中,一个惯性思维让我错了很多,jsoncpp中有自己的迭代器,我就很自然的使用了->
语法,结果报错,然后深入代码里瞧了眼,居然只有*
,你看,这就是问题.虽然可以说jsoncpp没有很好的实践C++的风格,但是如果没有操作符重载,我也就不抱这样的希望,也就不用浪费这么多的时间
再比如赋值构造函数,jsoncpp中这个的实现同复制构造函数不一样,导致一种用法是对的,另一种用法就是错误,只有打了小patch之后才能正常使用,你看,又是小小的语法糖.
再比如C中经典的typedef,有多少次为了少写几个字母结果弄得整个程序都很难堪?数过么?反正现在除了那些不想让别人看到但又必须给别人开放的类型,或者在模块内部为了简化类型声明(比如函数指针啊之类的),我极少使用typedef了.
总结
语法糖很好,但不能就此放松警惕,当然,以上的错误都是小错误,仔细的编程,良好的测试确实可以避免,但是与其事后自己发现,不若让编译器事前发生,能在编译期解决的问题,不拖到运行时来处理
语法糖虽好,可不要贪杯哦