[TL]只用C语言而不用C++的一个总结,欢迎大家拍砖。

943 views
Skip to first unread message

LeeoNix

unread,
Oct 21, 2011, 11:49:19 AM10/21/11
to TopLanguage
好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。

我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。

而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给“宠坏”了。

1、变量,该死的变量。

变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要“随意”的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。

我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说“随便”声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。

过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于“静态”检查,现在才明白。很多隐患实际就是坏习惯养成的。

2、析构函数,该死的析构函数。

我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了“随意”二字。其实……惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。

多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了……

Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫“result”的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。

我看到别人转载的Jasone Tee写了一个文章A return to Good Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?

3、思念模板,但忍住不用。

3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The C++ Programming Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。

4、写个库,然后再写个工具去为库服务。

请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c" "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。

我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。

而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。

5、class的封装真的有那么好吗?

Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。

如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。

我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。

Hub Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。

6、干好一件事。

Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。

FIXprotocol设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的FAST协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,这里可以下载看看。我看了这个给我的感觉是,我这些年到底做了些什么,怎么写的代码就没长进?

那什么才是“干好一件事”,还是Hub Scott写那个Stack例子,看完之后曾经和别人争论过Pop要不要返回值的事情。而STL也是这么做的,pop是pop,而top是top,传统介绍栈的描述,遵循了“弹出”这个概念,pop是有返回值。而现在用STL的栈,逐渐都接受了top结合pop的方式。

我继续重新审视以前写的代码。那个所谓封装的D3D的类,其结构严重违反干好一件事的原则,唉,越看越觉得,觉得……真的很难堪。
而干好一件事,和简单性。真的没个真正的标准,我还只是凭感觉判断。

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

说到这里,没多少可说的了。C++的危险就是太多概念,太多“方便”的东西提供。优点和缺点并存。

Brain Kernighan和Rob Pike的《程序设计实践》真的是一本太好的书了,被我看了不知道多少遍了。在书里,一章提供CSV文件读写的代码里,他们用C++写了一个读写类。而且书里面介绍了C++比C语言优势的地方。《Hackers Delight》这本书开始就说,用C++而像用C一样。

坚持让自己用纯粹C语言的时候,我不断审视我以前用C++的问题所在。所谓OOP能一统天下的理论,还有被吹捧上了天的设计模式。这些年在中国被宣传的天花乱坠。虽然说OOP(OOD)还有设计模式我用的很熟,但该是被浇冷水的时候了。

写到这里,我的脸皮到早就没了,呵呵,欢迎拍砖。


HaoPeiQiang

unread,
Oct 21, 2011, 12:15:25 PM10/21/11
to pon...@googlegroups.com
所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。

2011/10/21 LeeoNix <leeo...@gmail.com>



--
Tinyfool的Blog http://tiny4.org/blog/

windstorm

unread,
Oct 21, 2011, 12:31:46 PM10/21/11
to pon...@googlegroups.com
Objective-C确实也挺好,但仅限于苹果平台。其实我觉得你可以去看看Rob Pike他们搞的Go。

我没用过C++,所以不清楚和C++比的优劣。但Go是我见过的第一种结合C和Python的很多优点的语言,原生并行。尤其值得一提的是其interface设计及其优雅而高效,让我觉得所有程序语言都应该这样设计。Go是天生的服务器语言,但写本地程序一样很方便。

在我用过的主流语言中(C/Python/Java/Objective-C),Go是唯一一种让我觉得“程序就该这样写”的。

----------------------------------------------------------------------------------
Yours Sincerely
Kun

gplus.to/kunli


2011/10/21 HaoPeiQiang <HaoPe...@gmail.com>:

HaoPeiQiang

unread,
Oct 21, 2011, 12:34:42 PM10/21/11
to pon...@googlegroups.com
Go我觉得不错,不过我还是更喜欢OC,哈哈

2011/10/22 windstorm <likunar...@gmail.com>

windstorm

unread,
Oct 21, 2011, 12:45:22 PM10/21/11
to pon...@googlegroups.com
如果专注点是苹果平台,OC当然是不二选择。

我当年学完OC的最大感触就是,要是Java有其一半优雅和高效就好了

HaoPeiQiang

unread,
Oct 21, 2011, 12:48:19 PM10/21/11
to pon...@googlegroups.com
我最大的感触是当年人类居然选择了C++,真是一条不归路,C++是违反大多数人类智商水平的东西,太难了,我刚学的时候还觉得简单,后来才发现根本不是我能学会的。

2011/10/22 windstorm <likunar...@gmail.com>

windstorm

unread,
Oct 21, 2011, 12:50:27 PM10/21/11
to pon...@googlegroups.com
所以我从来就没想过要碰它:)

LeeoNix

unread,
Oct 21, 2011, 12:57:21 PM10/21/11
to pon...@googlegroups.com
至少有一点,C++是不多的“编译类语言”,现在编译类语言真的少的可怜了。但被吹捧也与微软的强力推广有联系。

LeeoNix

unread,
Oct 21, 2011, 7:49:01 PM10/21/11
to pon...@googlegroups.com
呵呵,有一个巨大的问题,就是用DirectX技术做游戏,而我又要做游戏。现在就算用gcc编译游戏的库绕弯子很麻烦,何况用其他的。C++做游戏有其优势,而方法也比较合适。语言适用。

GFree.Wind

unread,
Oct 21, 2011, 9:14:38 PM10/21/11
to TopLanguage
一直属于潜水员。。。。
今天看到楼主这个帖子出来冒个泡吧。

我一直都是使用C语言,但是我却也很喜欢C++,喜欢面向对象。但是毕业后,由于工作都是Linux偏底层的开发,所以工作中都是C语言。
但是由于自己对C++的偏好,一直也没有放弃C++。

我个人觉得语言存在即有它的合理性,C++其实本身没有什么问题,也很好用。
它的缺点就是语法太复杂,太丰富了。不浸润个10年以上,说精通C++,纯属笑话。
而很多人并没有这个水平,滥用C++的特性和OOP的方法,结果写出来的东西根本没法维护,也很难看。
对于Scott Meyers,我认为他绝对是大师级的认为。一般的C++程序员如果能够真正理解其Effective系列的著作,写出的C++程序绝
对不会有大问题。

而C呢,正是因为其语法很简单,基本的语法和适用,一般人大概好好整个儿三五年的也很熟练了。基本上就不会犯一些愚蠢的错误。
当然C的细节其实也很多,前两天看了一遍C99标准,也找到了一些自己以前误解或者不甚清晰的地方。

下面针对楼主说的几个方面,我说说我的观点吧
1. 变量:
我以前的编程风格也是将变量放在函数入口。现在如果该变量的只是临时使用的话,我更喜欢就近定义;
2. 析构:
我还是比较喜欢C++的析构的。但是我要用它的话,基本上就是用析构去释放资源,用类封装资源的申请。
别的不说,现在我的代码中,我基本上可以保证很少有或者没有资源泄漏,可是你的同事,老的代码中呢?
以前我去检查一个内存泄漏问题,结果发现有很多处内存没有释放。检查内存泄漏固然可以用valgrind,但是它不是万能的,有时候确实需要
review代码才能找到问题。
这个工作量可不小。
3. 模板:
模板不能滥用,就如同C中的宏定义。但有时候又无法避免,那么使用模板的话,还会比宏多一些检查。
5. 类的封装:
这个东西不好说。就是一个度的把握。简单的结构,就用struct,复杂的该封装就封装。


上面是我的一些拙见,水平不高,仅供大家讨论。
最后再总结一句吧。个人认为C++语言不错,但是如果不懂其本质而滥用,写出的代码肯定没法看,但这不是C++的错。
我觉得楼主觉得C++不爽的原因,可能被一些味道不好的代码给郁闷了。


On Oct 22, 12:31 am, windstorm <likunarmstr...@gmail.com> wrote:
> Objective-C确实也挺好,但仅限于苹果平台。其实我觉得你可以去看看Rob Pike他们搞的Go。
>

> 我没用过C++,所以不清楚和C++比的优劣。但Go是我见过的第一种结合C和Python的很多优点的语言,原生并行。尤其值得一提的是其interface 设计及其优雅而高效,让我觉得所有程序语言都应该这样设计。Go是天生的服务器语言,但写本地程序一样很方便。


>
> 在我用过的主流语言中(C/Python/Java/Objective-C),Go是唯一一种让我觉得"程序就该这样写"的。
>
> --------------------------------------------------------------------------- -------
> Yours Sincerely
> Kun
>
> gplus.to/kunli
>

> 2011/10/21 HaoPeiQiang <HaoPeiQi...@gmail.com>:


>
>
>
>
>
>
>
> > 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的 ,而且有一个非常棒的类库,没有C++的一切负担。
>

> > 2011/10/21 LeeoNix <leeoni...@gmail.com>
>
> >> 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而 我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> >> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
> >> Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效 仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。


>
> >> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> >> 1、变量,该死的变量。
>

> >> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉 我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得 和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候 把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> >> 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于 乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for


> >> (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>

> >> 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发 现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> >> 2、析构函数,该死的析构函数。
>
> >> 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以 在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。 注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而 随意的return的根源,是我随意的使用了析构函数。
>
> >> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
> >> Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的got o,后来想想goto还是算了......
>
> >> Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返 回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫"result"的变量使用,赋值之后才根据情况return,我还把我的Lua代码 很多地方也做了类似的修改。数据的流向很容易被控制。


>
> >> 我看到别人转载的Jasone Tee写了一个文章A return to Good

> >> Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈 巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> >> 3、思念模板,但忍住不用。
>
> >> 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄 个模板就好了。其实是看了Stroustrup在The
> >> C++ Programming
> >> Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了"玩"模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正 事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了 测试量,比单纯写个非模板的代码要麻烦数倍。


>
> >> 4、写个库,然后再写个工具去为库服务。
>
> >> 请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对"参数"这个,类似处理 "-c"

> >> "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Window s,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可 以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起 考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
>
> >> 我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了"记法"这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用 于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给L ua用,并没有仔细研究这个工具。


>
> >> 而这种,"写个库,然后写个工具"的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
>
> >> 5、class的封装真的有那么好吗?
>
> >> Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
>

> >> 如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据, 写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用c lass的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个se lf干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。


>
> >> 我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真 的不是个好习惯。
>
> >> Hub
> >> Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人 ,其实他以后后悔了。
>

> >> 我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的 东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric
> >> Raymond对C++的评价还是相对客观的,我最近才知道Alex
>
> ...
>
> read more >>

Yuantai Du

unread,
Oct 21, 2011, 9:18:59 PM10/21/11
to pon...@googlegroups.com
C在底层方面的优势是C++怎么都无法比拟的。

Linus Torvalds 曾经说过他不用C++在kernel programming的原因。除去他感情性的东西,技术性的两点是:
1)在kernel中无法handle exception
2)无法memory allocation
其实这两点都不是真实的"无法",但是不可否认,在kernel programming中,要做到exception handling
和memory allocation要付出的代价非常大(比如:怎么样用kalloc和free实现placement
new?),一个例子就是微软把kernel C++化的代价也非常大。

除了kernel programming,在user
land编程的话,我觉得C++还是有很大优势的。毕竟太多的功能和概念也提供了足够强大的优化能力。C++的门槛其实非常高,完全不是只用一两年就可以精通的。但是对于老手来说,任何其他语言可以实现的概念都可以相对简单地在C++实现,兼顾性能和结构。

2011/10/21 LeeoNix <leeo...@gmail.com>:


> 呵呵,有一个巨大的问题,就是用DirectX技术做游戏,而我又要做游戏。现在就算用gcc编译游戏的库绕弯子很麻烦,何况用其他的。C++做游戏有其优势,而方法也比较合适。语言适用。
>
> 在 2011年10月22日 上午12:15,HaoPeiQiang <HaoPe...@gmail.com>写道:
>>
>>
>> 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
>>
>> 2011/10/21 LeeoNix <leeo...@gmail.com>
>>>
>>>
>>> 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>>>
>>> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
>>> Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>>>
>>> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>>>
>>> 1、变量,该死的变量。
>>>
>>>
>>> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>>>
>>>
>>> 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
>>> (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>>>
>>>
>>> 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>>>
>>> 2、析构函数,该死的析构函数。
>>>
>>>

>>> 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
>>>
>>> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
>>> Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了......

>>> 我继续重新审视以前写的代码。那个所谓封装的D3D的类,其结构严重违反干好一件事的原则,唉,越看越觉得,觉得......真的很难堪。

LeeoNix

unread,
Oct 21, 2011, 9:34:06 PM10/21/11
to pon...@googlegroups.com
C++的优势,自从我2002年用起到现在,就没感觉到有多大。真的,学习C++从惊喜到狂热,从狂热到冷静,从冷静到哀叹。不止一个牛人在反C++的立场上说反对C++的话了。这些人的话都是理智而且份量重,让我不得不重新审视为什么要用C++这个问题。

就像会思考的人,总会突然有一天思考:人为什么活着。很多会继续思考人为什么存在与社会上(或者存在于地球上)。甚至会继续思考,人和宇宙的联系之类的。几年前,我和Cnpack开发组的朋友们在干锅居很深入的交流过人与宇宙的关系,大家发表感慨真的很踊跃,不亏都是程序员……而我当时都很异样为什么大家都在不同的时刻都往宇宙去考虑了呢,是全员不是个别……

所谓反思使用C++的问题,起始和思考到人与宇宙的途经。有的时候感觉累了,就会胡思乱想一下。如果活的很开心,换言之用C++很开心的人,估计不会有我类似的想法。

痛定思痛大概如此了。

LeeoNix

unread,
Oct 21, 2011, 9:43:45 PM10/21/11
to pon...@googlegroups.com
你说的所有的喜欢的地方。我也很喜欢,就因为喜欢,我才用了这么久,超过五年以上。

但我写这个的目的就是,你的喜欢是不是有益的。是不是真正值得考虑的。当你的喜欢不能用了,想想为什么你的喜欢不能存在于其他地方,而别的语言为什么不想要这种“喜欢”?

前几天我和一个朋友交流,有时候在思考,为什么人不能随心所欲的或者呢?人有些嗜好和习惯是不是应该违逆自己的心情不要作?

比如我们喜欢的熬夜,晚起。喜欢的吸烟喝酒,喜欢的其他嗜好。

The Pragmatic Programmer是一本好书,(注意我一直都很鄙视《程序员修炼之道》这个翻译书名,我很费解。)书的作者一开始就重点说不要总是习惯一种东西,而是理解不同场合的优点,适时的更换思维才有益。这么久我才真正理解程序里面的某些对于习惯的依赖,真的是思维的巨大障碍。

GFree.Wind

unread,
Oct 21, 2011, 11:24:48 PM10/21/11
to TopLanguage
讲得有道理呵,尤其是这一句----想想为什么你的喜欢不能存在于其他地方,而别的语言为什么不想要这种 "喜欢"?
我可以再补充一点。也许正是因为我工作中没有用c++,没有深入的去使用,没有大规模代码量的实践,才会有这种单纯的喜欢。

On Oct 22, 9:43 am, LeeoNix <leeoni...@gmail.com> wrote:
> 你说的所有的喜欢的地方。我也很喜欢,就因为喜欢,我才用了这么久,超过五年以上。
>
> 但我写这个的目的就是,你的喜欢是不是有益的。是不是真正值得考虑的。当你的喜欢不能用了,想想为什么你的喜欢不能存在于其他地方,而别的语言为什么不想要这种 "喜欢"?
>
> 前几天我和一个朋友交流,有时候在思考,为什么人不能随心所欲的或者呢?人有些嗜好和习惯是不是应该违逆自己的心情不要作?
>
> 比如我们喜欢的熬夜,晚起。喜欢的吸烟喝酒,喜欢的其他嗜好。
>
> The Pragmatic

> Programmer是一本好书,(注意我一直都很鄙视《程序员修炼之道》这个翻译书名,我很费解。)书的作者一开始就重点说不要总是习惯一种东西,而是理解不 同场合的优点,适时的更换思维才有益。这么久我才真正理解程序里面的某些对于习惯的依赖,真的是思维的巨大障碍。

> > 注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞 一样。而


> > 随意的return的根源,是我随意的使用了析构函数。
>
> > > >> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
>
> > Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的got
> > o,后来想想goto还是算了......
>
> > Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返
> > 回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫"result"的变量使用,赋值之后才根据情况return,我还把我的Lua代码
> > 很多地方也做了类似的修改。数据的流向很容易被控制。
>
> > > >> 我看到别人转载的Jasone Tee写了一个文章A return to Good
>
> > Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈
> > 巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> > > >> 3、思念模板,但忍住不用。
>
> > 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄
> > 个模板就好了。其实是看了Stroustrup在The
> > > >> C++ Programming
>

> ...
>
> read more >>

GFree.Wind

unread,
Oct 21, 2011, 11:29:47 PM10/21/11
to TopLanguage
刚才忘说了一点,《The Pragmatic Programmer》确实不错,大师的总结。
很多观点都是高屋建瓴的。尤其是说对于编程语言的依赖,鼓励技术人员换一种不同方式的编程语言去学习。
我就觉得目前我对C的依赖太大了。可是又不太喜欢脚本语言,如perl,python等,只会比较基本的应用,浅尝辄止。

On Oct 22, 9:43 am, LeeoNix <leeoni...@gmail.com> wrote:

> 你说的所有的喜欢的地方。我也很喜欢,就因为喜欢,我才用了这么久,超过五年以上。
>
> 但我写这个的目的就是,你的喜欢是不是有益的。是不是真正值得考虑的。当你的喜欢不能用了,想想为什么你的喜欢不能存在于其他地方,而别的语言为什么不想要这种 "喜欢"?
>
> 前几天我和一个朋友交流,有时候在思考,为什么人不能随心所欲的或者呢?人有些嗜好和习惯是不是应该违逆自己的心情不要作?
>
> 比如我们喜欢的熬夜,晚起。喜欢的吸烟喝酒,喜欢的其他嗜好。
>
> The Pragmatic

> Programmer是一本好书,(注意我一直都很鄙视《程序员修炼之道》这个翻译书名,我很费解。)书的作者一开始就重点说不要总是习惯一种东西,而是理解不 同场合的优点,适时的更换思维才有益。这么久我才真正理解程序里面的某些对于习惯的依赖,真的是思维的巨大障碍。

> > 注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞 一样。而


> > 随意的return的根源,是我随意的使用了析构函数。
>
> > > >> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
>
> > Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的got
> > o,后来想想goto还是算了......
>
> > Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返
> > 回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫"result"的变量使用,赋值之后才根据情况return,我还把我的Lua代码
> > 很多地方也做了类似的修改。数据的流向很容易被控制。
>
> > > >> 我看到别人转载的Jasone Tee写了一个文章A return to Good
>
> > Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈
> > 巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> > > >> 3、思念模板,但忍住不用。
>
> > 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄
> > 个模板就好了。其实是看了Stroustrup在The
> > > >> C++ Programming
>

> ...
>
> read more >>

Yili Zhao

unread,
Oct 22, 2011, 1:14:05 AM10/22/11
to pongba
好像大部分的三维图形引擎都是用C++写的,像场景图这样的数据结构,用C++描述应该比用C更合适一些。
从wikipedia上面看到,ID公司的引擎,从第4个版本开始,也把编程语言从C换成了C++。

参考资料:
List of game engines: http://en.wikipedia.org/wiki/List_of_game_engines

--
Yili Zhao

rexfield

unread,
Oct 22, 2011, 1:26:15 AM10/22/11
to TopLanguage
虽然编程时间不长,但是也接触过几门语言了,目前一直是用 C 做主体,偶尔用 C++/C#。
个人觉得 C++ 最大的贡献就是在类中提供方法(可能是我比较懒的原因,哈~~~)。
在用 C++/C# 编程的时候,无论要实现什么功能,我只用类中的数据成员和方法成员,其他的模板、继承什么的一概不理(除非 RAD 自动生成
的)。

LeeoNix

unread,
Oct 22, 2011, 1:29:05 AM10/22/11
to pon...@googlegroups.com
是的,在这方面C++的优势不可否认。在Unix编程艺术,里面,Eric Raymond说C++在GUI和游戏这两方面,有着比C语言强的优势,而且他称赞了Qt库。

yuan zhu

unread,
Oct 22, 2011, 7:11:38 AM10/22/11
to pon...@googlegroups.com
表达力更强的语言,对于变化更快的业务,当然有更加的适应力咯。

其实c语言标准如果肯接受gcc的嵌套函数扩展,那就功德无量了。(VC 编译器如果还不跟进我就彻底把你枪毙了)

朱金灿

unread,
Oct 22, 2011, 8:41:05 AM10/22/11
to pon...@googlegroups.com
 工作上使用C++,业余时间使用过C函数(Win API)进行开发。使用C API开发的感受是:
1.灵活,同时经常使用API的话可以加深对底层的理解。
2.但单纯使用C函数开发有些地方让人不舒服。一是资源释放,说实话我还是喜欢用析构函数来释放资源;二是如果单纯过程式总是难免产生一些全局变量,对于全局变量这类东西,我希望最好是没有。

       所以我是希望这样的开发:尽量自己通过封装API实现对象来进行开发,一方面可以用C的高效,避免使用一些臃肿的C++框架,另一方面可以应用面向对象的优点。不过说实话这样做,对新手并不合适。

shiwei xu

unread,
Oct 22, 2011, 10:10:42 AM10/22/11
to pon...@googlegroups.com
别纠结了,用 Go 语言吧。
我是 C++ 狂热爱好者,直到遇到了 Go 语言为止。

--
许式伟

2011/10/21 LeeoNix <leeo...@gmail.com>

Yongwei Wu

unread,
Oct 22, 2011, 10:30:51 AM10/22/11
to pon...@googlegroups.com
C++的最大优势应该是RAII,也就是析构函数。在资源管理方面,用好RAII,就不该会发生资源泄露。RAII是异常等很多C++特性的基础。

C++不容易用好。但对我而言,C++可以写出比C更灵活的、更安全、更紧凑、更具有表达力的代码。

语言是可以决定思维模式的。为什么C的代码最容易出现缓冲区溢出,就是因为C的程序员最容易使用固定缓冲区大小的方式——这对C来讲是最容易、最自然的方式。大部分其他语言都不是如此。

2011/10/22 rexfield <redwo...@gmail.com>:

--
Wu Yongwei
URL: http://wyw.dcweb.cn/

LeeoNix

unread,
Oct 22, 2011, 10:31:51 AM10/22/11
to pon...@googlegroups.com
不用Go,语言发展到现在。语言的优秀与否本身已经不特别重要了,关键是合适的库以及社区支持。C++用好了也是没什么问题的,V8用C++写的HipHop也是用C++做的。Javascript和PHP遇到瓶颈了,求助于C++。而C++自己呢?只不过反思一下自己。

Jiliang Li

unread,
Oct 22, 2011, 10:34:50 AM10/22/11
to pon...@googlegroups.com
C的问题是没有类似STL的标准库,很多东西都需要自己去山寨

LeeoNix

unread,
Oct 22, 2011, 10:53:54 AM10/22/11
to pon...@googlegroups.com
何谓山寨?有个叫cstl的库,不知道你用过没有。
不过这里我反问一下。为什么不自己写一些库呢?

有时候自己写的库和用stl都是难以取舍的,这点在《程序设计实践》里,Kernighan和Pike在链算法明确指出,那时候的deque是有问题的,用list效果会更好。换句话说,用stl真的有保障吗?而Kernighan和Pike写下那个代码的时候的deque和现在的deque肯定是有区别的。但还是那个问题,真的有保障吗?

德国人开源的游戏引擎Nebula,一个stl都没用。而经典的ACE,QT库,都有自己的容器,也是把stl排除在外。ACE和QT份量就已经重了。何况还有好多例子摆在面前。而他们为什么这么做?他们为什么要舍弃STL,而自己开发容器和算法?为什么对stl持不信任态度?

说起这个,我就想起Linus在写git的那里,那场骂架里面的一些话了。

yuan zhu

unread,
Oct 22, 2011, 11:37:46 AM10/22/11
to pon...@googlegroups.com
兄弟,读书但求甚解。

1.那个时代的deque的问题,特指vc6的std::deque实现效率较低。
2.ACE和QT,出生的年代都比STL早,有一套自己替代的系统很正常。至于为什么一直还保留这些不能用于stl算法的容器,二者给出的答案相同:为了兼容那些不提供stl的特殊编译环境。兄弟你不会没听说过android
ndk吧。

没事写c++库(高质量的库),是件很奢侈的事情。兄弟你太小看自己写c++库的难度了。

另外兄弟那些连续的反问句,读起来让人很迷糊。。。颇有外交部发言人之风。

On 10/22/11, LeeoNix <leeo...@gmail.com> wrote:

>>>>> Code<http://www.theserverside.com/tip/A-return-to-Good-Code>
>>>>> ,看了英文原文才发现CSDN也翻译转载 <http://sd.csdn.net/a/20110323/294448.html>


>>>>> 了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>>>>>
>>>>> 3、思念模板,但忍住不用。
>>>>>
>>>>> 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The
>>>>> C++ Programming
>>>>> Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。
>>>>>
>>>>> 4、写个库,然后再写个工具去为库服务。
>>>>>
>>>>> 请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c"
>>>>> "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
>>>>>
>>>>>
>>>>> 我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。
>>>>>
>>>>> 而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
>>>>>
>>>>> 5、class的封装真的有那么好吗?
>>>>>
>>>>> Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
>>>>>
>>>>>
>>>>> 如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
>>>>>
>>>>>
>>>>> 我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。
>>>>>
>>>>> Hub
>>>>> Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
>>>>> 我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric
>>>>> Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。
>>>>>
>>>>> 6、干好一件事。
>>>>>
>>>>> Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
>>>>> 简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug
>>>>> McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。
>>>>>

>>>>> FIXprotocol <http://www.fixprotocol.org/>
>>>>> 设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的FAST<http://www.fixprotocol.org/fast>
>>>>> 协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,
>>>>> 这里 <http://www.fixprotocol.org/documents/2317/fastapi-1.0.zip>

yuan zhu

unread,
Oct 22, 2011, 11:55:51 AM10/22/11
to pon...@googlegroups.com
大道三千,道道有道理。

C++能够存在这么久,自有他存在的道理。尽管他生存条件恶劣,后无商业公司给他扩展库,前有因为资格老,编译器兼容性更好的C(C的很多优点其实就源自出道早,说白了。C89出现前后,c一样有很多兼容性问题),自己的模板库更是因为源码开放,被人千夫所指(同样是库函数,大家就盯着vc6的std::deque效率,干嘛就没人去瞅瞅msvcrt库memmove的效率?指责c++的人有时其实根本没注意自己毫无比较的对象。做c++的模板库是个超吃力不讨好的事,永远有人来指责你效率没有做到最佳,哪里的实现很笨拙。不像c语言那样,实现的源码都封装起来,闭着眼睛,一了百了,不用拉倒)。

其实那个cstl效率很低的。。。真的。有的库名字取的很牛,未必真的很牛。还有一个叫s11n的家伙。

Yuantai Du

unread,
Oct 22, 2011, 12:30:32 PM10/22/11
to pon...@googlegroups.com
C++的优势体现在其运行效率和编程效率的统一上。其他的大多数编程语言,从Smalltalk,java,
c#到Go,有足够高的编程效率,但是其编译后的运行效率则无法和C++相比,更不用说scripting
language了。这是由于这些高级语言的设计中,本身就已经包含了很多的masking,所以,在大多数时候,他们编程效率的提高隐含了运行峰值的下降。C++由于保留了C的大多数底层特性,所以保留了足够人工调整运行效率的空间。C语言有足够的运行效率,但是其编程效率比面对对象要差太多了。所以被局限在了底层编程。一个例外是苹果的ObjectiveC,
使用了大量的宏来达到面对对象。不知以后objective c 能否扩展到其他领域。

这些优势,可以在最能体现其特点的领域看到。如果去华尔街,大多数的公司,几乎所有的高频交易,都是用的C++,连java和C都不可以。因为他们非常在乎从5毫秒到3毫秒的优化,又必须快速编程,立刻用上。再比如现在很多的网络和存储器公司,如diligent(现在是ibm了)、netapp、equallogic(现在是dell)等,都是用的C++,因为他们需要大量的底层接口和运行效率。

C++的缺点,其实就在这些与其他语言的不同上面。也就是如你所说的,是这些庞大臃肿的概念和功能。因为这些其实是牛刀,如果去割鸡的话,很容易反而弄得一地鸡血。那些大牛对C++的批评,其实可以说都对,C++没有一个清晰明确的设计理念,甚至不能算是真正纯粹的面对对象。所以,所有其他语言都有其生存发展的空间,因为这才是常理:一种语言的设计原则,决定了这种语言的应用领域。C++并不适合web编程,但是有其适合的应用。

2011/10/21 LeeoNix <leeo...@gmail.com>:

Xavier Heruacles

unread,
Oct 22, 2011, 12:45:28 PM10/22/11
to pon...@googlegroups.com
以下是菜鸟对C++的理解:
我很不明白为什么现在还有那么多人讨论C++,貌似看看reddit, hacker news上,别人都是讨论clojure,scala等东东了。sicp上说衡量一个语言就是三个方面,primitive expressions, means of combinations and means of abstractions。当一个语言在这三方面上过分灵活而又到处是陷阱的时候(我是指C++,上面也说了没学够10年都不敢说精通C++,而C++难学也是众所周知的),为什么还在坚持着这个不趁手的工具呢?我想只有几个原因,一个是legacy code,那么多写好的C++库,游戏引擎等让相应的项目更容易往这已有的工具上靠,另一个我认为是很重要的原因就是工业界(尤其是决策者们)还缺乏足够的认识,每个公司老板都从别人那里听说写游戏,写什么什么需要C++(或者是别的语言,如java),从而导致学这个语言更有可能找到工作,从而......我想这也是为什么很多真正优秀的语言(如lisp)没真正流行起来的原因吧。
一个语言能在简洁和表达力上面有一定平衡,学起来用起来才会舒服,也可以节约更多的脑力资源对付本质问题。

2011/10/22 yuan zhu <zy49...@gmail.com>

tangl_99

unread,
Oct 22, 2011, 2:52:06 PM10/22/11
to TopLanguage
没有apple的机器怎么试Objective-C?


On Oct 21, 12:15 pm, HaoPeiQiang <HaoPeiQi...@gmail.com> wrote:
> 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
>

> 2011/10/21 LeeoNix <leeoni...@gmail.com>


>
>
>
>
>
>
>
>
>
> > 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> > 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
> > Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> > 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> > 1、变量,该死的变量。
>
> > 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> > 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> > (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> > 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> > 2、析构函数,该死的析构函数。
>

> > 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
>
> > 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
> > Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了......

> ...
>
> read more >>

tangl_99

unread,
Oct 22, 2011, 2:53:26 PM10/22/11
to TopLanguage
单从面向对象语言设计来说,的确Java现在是很难很难超越了。


On Oct 21, 12:45 pm, windstorm <likunarmstr...@gmail.com> wrote:
> 如果专注点是苹果平台,OC当然是不二选择。
>
> 我当年学完OC的最大感触就是,要是Java有其一半优雅和高效就好了
>
> ----------------------------------------------------------------------------------

> Yours Sincerely
> Kun
>
> gplus.to/kunli
>
> 2011/10/21 HaoPeiQiang <HaoPeiQi...@gmail.com>:
>
>
>
>
>
>
>

> > Go我觉得不错,不过我还是更喜欢OC,哈哈
>
> > 2011/10/22 windstorm <likunarmstr...@gmail.com>
>
> >> Objective-C确实也挺好,但仅限于苹果平台。其实我觉得你可以去看看Rob Pike他们搞的Go。
>
> >> 我没用过C++,所以不清楚和C++比的优劣。但Go是我见过的第一种结合C和Python的很多优点的语言,原生并行。尤其值得一提的是其interface设计及其优雅而高效,让我觉得所有程序语言都应该这样设计。Go是天生的服务器语言,但写本地程序一样很方便。


>
> >> 在我用过的主流语言中(C/Python/Java/Objective-C),Go是唯一一种让我觉得"程序就该这样写"的。
>
> >> ----------------------------------------------------------------------------------
> >> Yours Sincerely
> >> Kun
>
> >> gplus.to/kunli
>
> >> 2011/10/21 HaoPeiQiang <HaoPeiQi...@gmail.com>:
>

> >> > 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
>
> >> > 2011/10/21 LeeoNix <leeoni...@gmail.com>
>
> >> >> 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> >> >> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
>
> >> >> Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> >> >> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> >> >> 1、变量,该死的变量。
>
> >> >> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> >> >> 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> >> >> (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> >> >> 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> >> >> 2、析构函数,该死的析构函数。
>
> >> >> 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
>
> >> >> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
>
> >> >> Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了......
>
> >> >> Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫"result"的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。
>
> >> >> 我看到别人转载的Jasone Tee写了一个文章A return to Good
>

> >> >> Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?


>
> >> >> 3、思念模板,但忍住不用。
>
> >> >> 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The
> >> >> C++ Programming
>
> >> >> Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了"玩"模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。
>
> >> >> 4、写个库,然后再写个工具去为库服务。
>
> >> >> 请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对"参数"这个,类似处理"-c"
>
> >> >> "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
>
> >> >> 我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了"记法"这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。
>
> >> >> 而这种,"写个库,然后写个工具"的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
>
> >> >> 5、class的封装真的有那么好吗?
>
> >> >> Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
>
> >> >> 如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
>

> ...
>
> read more >>

LeeoNix

unread,
Oct 22, 2011, 7:16:02 PM10/22/11
to pon...@googlegroups.com
VC6? 你说的是Plauger实现的那个版本吗?针对使用deque的代码的作者,我写了名字了。Brain Kernighan是谁?Rob Pike是谁?你指望这俩老家伙用Windows写测试代码?你是不是移步到Google搜索一下这两个人的背景?然后在说你的"VC6"呢?不好意思,我又连续反问了,你可以继续说我像外交官。

我上面说了,我悲哀在Windows下工作了这么久,看你的“特指”VC6,让我觉得你应该和我一样应该悲哀,继而应该努力脱离Windows环境,拥抱更自由的环境。

没错,我就是在小看,而且我是从2002年开始学用C++到2005年真正开始在工作中用C++到今天的痛定思痛的反思和质疑。德国人的Nebula库是不是比STL的年代晚,但是通篇的库你看不到一个std的符号,你可以看到世面上有不少基于Nebula写的游戏,现在还在很好的跑着。我也提了,类似的例子不止一个。还有很多“其他”的。而且还不少不用STL的。我手里还有个Medusa库,写的很漂亮,虽然开源,但是没有宣传出去,不是太出名。但也是通篇看不到一个std符号。

你说"VC6"的版本我还又针对STL多说一下。VC用了P.J. Plauger的个人版本,微软还付钱给Plauger,还有SGI STL的比较官方的版本,还有STLport这儿可移植的版本。而官方的SGI STL经测试反而还不如STLport,该测试是本人测试过的,网上你还可以找到其他人比对各个版本STL性能的文章,请自行搜索。还有Rouge Wave STL,这是C++ Builder用的版本,还有古老的HP STL。那我问你,你选那个版本的STL?虽然接口都一样。性能呢,你就一点都没有怀疑过?

还有STL提供的string库,说着天花乱坠,可是真正要用到实际的人都不喜欢。我也看到很多代码,STL大部分都用,唯独string自己去写了。自己写string,就不得不自己写有围绕string使用的stream库。

我以前看《老友记》,罗斯拿来各种化石和标本,想尽办法想在进化论上去说服菲比,但是菲比很大声的质问罗斯:你就从来没有怀疑过进化论是不是对的吗?罗斯沉默了,然后拿着“证据”跑了。

我这里再次像外交官一样反问你:你就真正没有怀疑过STL的能力问题?性能问题?没有怀疑过STL自身的存在?ISO虽然规定了C++的标准,但是这个STL,就我这里数着就5个了。当你用一个稳定的项目去做事,你真的非常信任编译环境给你提供的库?

再提另外一个质疑,那个被吹上天的boost库。

LeeoNix

unread,
Oct 22, 2011, 7:58:39 PM10/22/11
to pon...@googlegroups.com
看到这里,我很质疑你说的“编程效率”的评价。但我对此不做评价,因为我已经不是面向对象的狂热者了,所谓的面向对象的效率,我这么多年没见有多好过。

说到这里又让我想起Linus的有关git的骂架了。其实Linus在那个有关git骂架里面,开始言辞激烈,后面却说得很中肯。

一句话总结:C++让人没有把心放到业务上。

Linus为了设计git,甚至用Shell和Perl设计原型,然后逐渐替代这些代码。最初的git确实很不易用,但是git的核心很早就被设计好了,外面的修正为易用就好了。

那个骂架过去很久了,git现在很流行。而我越来越看Linus的骂架顺眼了,不是个人崇拜的相信,是经历过之后才感觉Linus其实不管是不是言辞激烈,说的都是真正的技术争论,而且说的中肯。

特别Linus批评的,“完全是屁话。字符串/内存管理根本无关紧要。还是去看看源代码吧(我敢打赌你没有看过)。这不是重要的部分,而且也不复杂。唯一真正重要的部分是设计

我过了这么久才明白这个。Dmitry Kakurin和其他C++程序员一样,还是一个Coder,没有一个跳出去看项目的角度分析业务,看设计,而着眼于这些细节。其实这就是C++程序员的通病,而我作为C++程序员的一员,其实也是如此。而分析业务,设计的能力,和Java程序员比起来,简直让人羞愧,我也曾经作为羞愧的C++程序员一员,去批评Java的效率问题,但Java效率再差也把项目漂亮的搞好了。

程序设计语言无形中影响了人的思维方式。

Linus和Dmitry Kakurin说设计,而Dmitry Kakurin却在批评git的细节。然后我退一千步,做git的不是Linus,而是其他人,他的技术没有Linus那么牛,但是他很好的完成了git的核心业务,效率再差,也被快速开发为一个产品投放使用了,剩下的就是调优而已。何况Linus亲自操刀。

而实际的项目里,项目带头人唯技术先进的,毁了多少项目。比如我举个实际的例子,不是国外的。

阿里巴巴贸易通,以前就是个垃圾技术生成的IM,很多东西没做好实际上是用网页做的,虽然烂但是他快速投放市场了,大家接受这个产品了。而现在淘宝旺旺到阿里旺旺的版本,阿里巴巴在这方面做的很出色。而相比,盛大的圈圈项目,吹了那么久。就我在盛大的那段时间内,整整一年就没看到一个完整的东西出来,就是内部用的版本也是麻烦不断,我很是费解。现在你在世面上还看得到有人在用盛大圈圈吗?

反思啊。所以才艰难的决定就是:不用C++

LeeoNix

unread,
Oct 22, 2011, 8:12:26 PM10/22/11
to pon...@googlegroups.com
抱歉。我看了下书,俩老家伙还是在Windows下测试了。

他们在测试后最后的总结是:“我们也认为,STL作为C++的一个新部分,仍然受到不成熟实现的损害。在使用STL的不同实现或使用不同数据结构时,导致的性能变化是不可预测的。”

LeeoNix

unread,
Oct 22, 2011, 8:24:20 PM10/22/11
to pon...@googlegroups.com
其实C++,让人有理由相信其能力。牛人如Dijkstra,晚年都是在研究C++度过的。

可是,很多人都像我这样,没有学到C++的好处,却被很多“好玩”的东西给吸引并花掉大量的精力在上面,如:模板,上面提到,我竟然成了一个模板“玩家”,而C++好玩的地方,不止一点,很多地方都很好玩。

Stroustrup意识到这个了,所以他要致力于C++教学。但很多人都是自学的,C++设计本身就并没有引导程序员合理的使用它,而形成逆反正交性原则的一个庞然巨物。

这也是我为什么写这个标题,用C而不用C++。

让我再次用好C。

tangl_99

unread,
Oct 22, 2011, 8:57:43 PM10/22/11
to TopLanguage
我们做算法的,也基本上也只用Java。或者再用点matlab。

本来我们要实现的各种算法逻辑都很复杂,哪有心思去搞什么C++的优化。而且,对于我们来说,C++和Java那点速度的差别根本可以忽略。我们只关心
一个算法是O(N^2), O(N)还是O(NlogN)。

On Oct 22, 7:58 pm, LeeoNix <leeoni...@gmail.com> wrote:
> 看到这里,我很质疑你说的"编程效率"的评价。但我对此不做评价,因为我已经不是面向对象的狂热者了,所谓的面向对象的效率,我这么多年没见有多好过。
>
> 说到这里又让我想起Linus的有关git的骂架了。其实Linus在那个有关git骂架里面,开始言辞激烈,后面却说得很中肯。
>
> 一句话总结:C++让人没有把心放到业务上。
>
> Linus为了设计git,甚至用Shell和Perl设计原型,然后逐渐替代这些代码。最初的git确实很不易用,但是git的核心很早就被设计好了,外面的修正为易用就好了。
>
> 那个骂架过去很久了,git现在很流行。而我越来越看Linus的骂架顺眼了,不是个人崇拜的相信,是经历过之后才感觉Linus其实不管是不是言辞激烈,说的都是真正的技术争论,而且说的中肯。
>
> 特别Linus批评的,"完全是屁话。字符串/内存管理根本无关紧要。
> 还是去看看源代码吧(我敢打赌你没有看过)。这不是重要的部分,而且也不复杂。唯一真正重要的部分是设计。"
>
> 我过了这么久才明白这个。Dmitry
> Kakurin和其他C++程序员一样,还是一个Coder,没有一个跳出去看项目的角度分析业务,看设计,而着眼于这些细节。
> 其实这就是C++程序员的通病,而我作为C++程序员的一员,其实也是如此。而分析业务,设计的能力,和Java程序员比起来,简直让人羞愧,我也曾经作为羞愧的C++程序员一员,去批评Java的效率问题,但Java效率再差也把项目漂亮的搞好了。
>
> 程序设计语言无形中影响了人的思维方式。
>
> Linus和Dmitry Kakurin说设计,而Dmitry
> Kakurin却在批评git的细节。然后我退一千步,做git的不是Linus,而是其他人,他的技术没有Linus那么牛,但是他很好的完成了git的核心业务,效率再差,也被快速开发为一个产品投放使用了,剩下的就是调优而已。何况Linus亲自操刀。
>
> 而实际的项目里,项目带头人唯技术先进的,毁了多少项目。比如我举个实际的例子,不是国外的。
>
> 阿里巴巴贸易通,以前就是个垃圾技术生成的IM,很多东西没做好实际上是用网页做的,虽然烂但是他快速投放市场了,大家接受这个产品了。而现在淘宝旺旺到阿里旺旺的版本,阿里巴巴在这方面做的很出色。而相比,盛大的圈圈项目,吹了那么久。就我在盛大的那段时间内,整整一年就没看到一个完整的东西出来,就是内部用的版本也是麻烦不断,我很是费解。现在你在世面上还看得到有人在用盛大圈圈吗?
>
> 反思啊。所以才艰难的决定就是:不用C++
>

> 在 2011年10月23日 上午12:30,Yuantai Du <yuantai...@gmail.com>写道:
>
>
>
>
>
>
>
> > C++的优势体现在其运行效率和编程效率的统一上。其他的大多数编程语言,从Smalltalk,java,
> > c#到Go,有足够高的编程效率,但是其编译后的运行效率则无法和C++相比,更不用说scripting
>
> > language了。这是由于这些高级语言的设计中,本身就已经包含了很多的masking,所以,在大多数时候,他们编程效率的提高隐含了运行峰值的下降。C++由于保留了C的大多数底层特性,所以保留了足够人工调整运行效率的空间。C语言有足够的运行效率,但是其编程效率比面对对象要差太多了。所以被局限在了底层编程。一个例外是苹果的ObjectiveC,
> > 使用了大量的宏来达到面对对象。不知以后objective c 能否扩展到其他领域。
>
> > 这些优势,可以在最能体现其特点的领域看到。如果去华尔街,大多数的公司,几乎所有的高频交易,都是用的C++,连java和C都不可以。因为他们非常在乎从5毫秒到3毫秒的优化,又必须快速编程,立刻用上。再比如现在很多的网络和存储器公司,如diligent(现在是ibm了)、netapp、equallogic(现在是dell)等,都是用的C++,因为他们需要大量的底层接口和运行效率。
>
> > C++的缺点,其实就在这些与其他语言的不同上面。也就是如你所说的,是这些庞大臃肿的概念和功能。因为这些其实是牛刀,如果去割鸡的话,很容易反而弄得一地鸡血。那些大牛对C++的批评,其实可以说都对,C++没有一个清晰明确的设计理念,甚至不能算是真正纯粹的面对对象。所以,所有其他语言都有其生存发展的空间,因为这才是常理:一种语言的设计原则,决定了这种语言的应用领域。C++并不适合web编程,但是有其适合的应用。
>

> > 2011/10/21 LeeoNix <leeoni...@gmail.com>:


>
> > C++的优势,自从我2002年用起到现在,就没感觉到有多大。真的,学习C++从惊喜到狂热,从狂热到冷静,从冷静到哀叹。不止一个牛人在反C++的立场上说反对C++的话了。这些人的话都是理智而且份量重,让我不得不重新审视为什么要用C++这个问题。
>

> > 就像会思考的人,总会突然有一天思考:人为什么活着。很多会继续思考人为什么存在与社会上(或者存在于地球上)。甚至会继续思考,人和宇宙的联系之类的。几年前,我和Cnpack开发组的朋友们在干锅居很深入的交流过人与宇宙的关系,大家发表感慨真的很踊跃,不亏都是程序员......而我当时都很异样为什么大家都在不同的时刻都往宇宙去考虑了呢,是全员不是个别......


>
> > 所谓反思使用C++的问题,起始和思考到人与宇宙的途经。有的时候感觉累了,就会胡思乱想一下。如果活的很开心,换言之用C++很开心的人,估计不会有我类似的想法。
>
> > > 痛定思痛大概如此了。
>

> > > 在 2011年10月22日 上午9:18,Yuantai Du <yuantai...@gmail.com>写道:
>
> > >> C在底层方面的优势是C++怎么都无法比拟的。
>
> > >> Linus Torvalds 曾经说过他不用C++在kernel programming的原因。除去他感情性的东西,技术性的两点是:
> > >> 1)在kernel中无法handle exception
> > >> 2)无法memory allocation
> > >> 其实这两点都不是真实的"无法",但是不可否认,在kernel programming中,要做到exception handling
> > >> 和memory allocation要付出的代价非常大(比如:怎么样用kalloc和free实现placement
> > >> new?),一个例子就是微软把kernel C++化的代价也非常大。
>
> > >> 除了kernel programming,在user
>
> > land编程的话,我觉得C++还是有很大优势的。毕竟太多的功能和概念也提供了足够强大的优化能力。C++的门槛其实非常高,完全不是只用一两年就可以精通的。但是对于老手来说,任何其他语言可以实现的概念都可以相对简单地在C++实现,兼顾性能和结构。
>

> > >> 2011/10/21 LeeoNix <leeoni...@gmail.com>:


>
> > 呵呵,有一个巨大的问题,就是用DirectX技术做游戏,而我又要做游戏。现在就算用gcc编译游戏的库绕弯子很麻烦,何况用其他的。C++做游戏有其优势,而方法也比较合适。语言适用。
>

> > >> > 在 2011年10月22日 上午12:15,HaoPeiQiang <HaoPeiQi...@gmail.com>写道:
>
> > 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
>

> > >> >> 2011/10/21 LeeoNix <leeoni...@gmail.com>


>
> > 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> > >> >>> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
>
> > Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> > >> >>> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> > >> >>> 1、变量,该死的变量。
>
> > 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>

> ...
>
> read more >>

Yongwei Wu

unread,
Oct 22, 2011, 10:06:05 PM10/22/11
to pon...@googlegroups.com
2011/10/23 LeeoNix <leeo...@gmail.com>:

> 看到这里,我很质疑你说的“编程效率”的评价。但我对此不做评价,因为我已经不是面向对象的狂热者了,所谓的面向对象的效率,我这么多年没见有多好过。
>
> 说到这里又让我想起Linus的有关git的骂架了。其实Linus在那个有关git骂架里面,开始言辞激烈,后面却说得很中肯。
>
> 一句话总结:C++让人没有把心放到业务上。

笑话,C就让人把心放到业务上了?没有RAII,没有对象,没有继承,容易发生内存泄漏和缓冲区溢出⋯⋯

一开始说C++不好,后来又说Nebula好,STL不好或者其实现不好。我觉得你自己思路有点不清。实现不好是可以提高的,特别是早期的实现不完善很正常——何况菜鸟程序员很可能做得更糟糕。方向正确才是重要的。

我是试过把C++的代码直接翻译成C的,缓冲区的管理放到C实在是很不方便,无怪乎C程序员习惯于使用固定大小的缓冲区。语言绝对可以影响思维。

如果你把太多力气放在玩C++上,这是你的问题。不要怪C++。有人已经说过了,这是把牛刀,用好不容易。反过来,用好了,就是绝对的利器。

maydayzm

unread,
Oct 22, 2011, 10:27:43 PM10/22/11
to pon...@googlegroups.com
说得其实蛮中肯的,太专注细节就看不到全貌,设计才是最为关键。

LeeoNix

unread,
Oct 22, 2011, 10:31:57 PM10/22/11
to pon...@googlegroups.com
对C会让人把心放到业务上来,因为他的玩具很少。
而玩C++的人,不止一个,是很多人,而且站在正交性原则上,C++是出了名的逆正交性的。

而你说的C的问题是“容易”而不是“绝对”。既然容易就避免就是了。
而像Ken Thompson,自始至终就让简单进行到极致。

Lee Duhem

unread,
Oct 22, 2011, 10:33:51 PM10/22/11
to pon...@googlegroups.com
設計最關鍵是沒錯的,但要由此推出實現不重要就杯具了,不幸的是
許多人偏偏就得出了這麼個結論,而且還是在他們沒有能力做好實現的
情況下。

2011/10/23 maydayzm <mayd...@gmail.com>:

Yang Xin

unread,
Oct 22, 2011, 11:36:11 PM10/22/11
to pon...@googlegroups.com
Gcc啊

杨欣

Shuo Chen

unread,
Oct 23, 2011, 12:11:47 AM10/23/11
to TopLanguage
用1999年的书上的话来评价2011年的STL,很好。

On Oct 23, 8:12 am, LeeoNix <leeoni...@gmail.com> wrote:
> 抱歉。我看了下书,俩老家伙还是在Windows下测试了。
>
> 他们在测试后最后的总结是:"我们也认为,STL作为C++的一个新部分,仍然受到不成熟实现的损害。在使用STL的不同实现或使用不同数据结构时,导致的性能 变化是不可预测的。"
>

> 在 2011年10月23日 上午7:16,LeeoNix <leeoni...@gmail.com>写道:
>

Chunlin Zhang

unread,
Oct 23, 2011, 12:16:15 AM10/23/11
to TopLanguage

On Oct 21, 11:49 pm, LeeoNix <leeoni...@gmail.com> wrote:
>
> 1、变量,该死的变量。
>
> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。

c99 应该可以,不过即使是c89,你可以可以在你想要"随意"声明变量的地方用花括号形成语句块,这样就可以"随意"声明了

yuan zhu

unread,
Oct 23, 2011, 12:25:01 AM10/23/11
to pon...@googlegroups.com

陈硕大家涵养真强啊。

我直接就不想理这种试图用月经贴或者不断引用名人名言来出名的“现代祢衡”,不管他是寻找明主还是就是想来发泄一通抑或是混个出名。

Yuantai Du

unread,
Oct 23, 2011, 12:28:49 AM10/23/11
to pon...@googlegroups.com
在我们说完C++的缺点之后,我们要说未来的方向是什么——是向高级语言的方向走,还是向低级语言的方向走。

你的标题让我感觉你想向低级语言方向走,而你辩论的多数内容,让我感觉是在批判C++的低级性。

什么是高级语言的特征?设计特征更向subject
domain的内在概念关系靠拢,就是说,更容易概括问题领域的模型,而实现细节揭露得更少。而低级语言呢?更与机器的实现细节相关,因此较难有清晰的设计。

你批评的东西,最初的一篇中的弱类型和析构函数都可以照搬过来批评C,不用析构函数,难道用free_pages会更简单吗?应该相反,因为这其实是低级语言的特征之一。

如果你批评的是C++的可读性和编程效率,那么你更不应该换成C,因为C的这些缺点更明显。你应该换成高级语言方向,去用Go,
scala,或者Scripting language,他们对实现细节的披露更少,对问题模型的概括更好。

然后,问题领域的特征与设计的选择息息相关。在OS级别上,除了汇编和C/C++,我极少极少看到任何其他语言;在涉及硬件的应用程序方面,C++占了统治地位;在要求高性能单机运算的金融软件方面,C++占了统治地位;在web
programming上,人们越来越多地远离C/C++,甚至远离Java;在Hadoop等并行运算方面,函数编程有很大的优越性。所以,语言特性已经在这里了,关键是需求特征。

就拿你举的Linus关于git的评论来说吧,“完全是屁话。字符串/内存管理根本无关紧要。”为什么?因为git的问题领域是代码管理,不是操作系统。他还有另一个更早的著名辩论,是关于kernel是否用C++的:
1) the whole C++ exception handling thing is fundamentally broken.
It's _especially_ broken for kernels. 2) any compiler or language that
likes to hide things like memory allocations behind your back just
isn't a good choice for a kernel. 3) you can write object-oriented
code (useful for filesystems etc) in C, _without_ the crap that is
C++."
在这里,他的第二个抱怨则是内存管理在C++中比在C中难很多。对照关于git的评论你就可以知道,他说的是针对问题领域,不是solution domain。

所以,回到你对“编程效率”的质疑上来,批评C++没有问题,但是要知道各个语言之间的不同到底是什么。如果批评的是C++的运行性能,那么C是更好的选择;如果批评的是C++的编程效率,那么C更有可能变得更差。

2011/10/22 LeeoNix <leeo...@gmail.com>:

LeeoNix

unread,
Oct 23, 2011, 1:03:13 AM10/23/11
to pon...@googlegroups.com
1999年的书又如何?我不因为你是谁而相信你的权威性。1999年的书的经典性,也是我反复看的一个原因。

而我没有看到2011年有什么“新的”STL摆在我的面前,如果所谓新的STL,请你给我下载的地方,我去看看STL是不是真的有能统一为一个能用的东西给大家用。string的效率是不是也足够通用的让我们能够在国际化上站住脚。

那个C++ 0x修正为C++2011之后,有什么值得让人称赞的地方,我还没看出来。

LeeoNix

unread,
Oct 23, 2011, 1:05:40 AM10/23/11
to pon...@googlegroups.com
又来了,中国人的劣根性之一。我刚在另外一个有关希腊的历史,发散思维了下,说了下中国的有关排资论辈侮辱权威的问题。

我不是因为他叫:陈硕。而相信他说的话。如果我不认同他说的话,我会逐一提出质疑并反驳。

而你最好不要提很么大家小家的来显示他的“资格”和能力,其实你是在侮辱陈硕!

LeeoNix

unread,
Oct 23, 2011, 1:07:23 AM10/23/11
to pon...@googlegroups.com
呵呵,C99这个我知道。其实我给很多初学者都推荐先用Delphi再用C++,有时候,变量以及变量初始化的问题,是初学者烦得错误。其实有时候何其不是老手时不时也会犯的错误?我只不过因此而反思自己。

Shuo Chen

unread,
Oct 23, 2011, 1:33:22 AM10/23/11
to TopLanguage
一方面自称不相信权威,一方面又把一本10多年前的书的结论(当时某个STL实现的性能测试结果)奉为圭璧,同样很好。
STL 也不需要去下载,用编译器自带的版本就好,g++ 4.x, VC++ 2008/2010 都很新。你不会还在用 VC6 古董吧?

水木 C++ 版最近有个很火的帖子, http://www.newsmth.net/bbstcon.php?board=CPlusPlus&gid=333585
其中我非常同意 pEE 的观点: http://www.newsmth.net/bbscon.php?bid=335&id=333645

就基础数据结构而言,动态数组(vector),双向链表(list),平衡二叉树(set/map),开链式哈希表
(unordered_{map, set})
的性能没什么可挑剔的,通用的容器库最好也就能写成这样了。当然你也可以构造一些特殊的例子把 STL 性能比下去。

On Oct 23, 1:03 pm, LeeoNix <leeoni...@gmail.com> wrote:
> 1999年的书又如何?我不因为你是谁而相信你的权威性。1999年的书的经典性,也是我反复看的一个原因。
>

> 而我没有看到2011年有什么"新的"STL摆在我的面前,如果所谓新的STL,请你给我下载的地方,我去看看STL是不是真的有能统一为一个能用的东西给大家 用。string的效率是不是也足够通用的让我们能够在国际化上站住脚。
>
> 那个C++ 0x修正为C++2011之后,有什么值得让人称赞的地方,我还没看出来。

LeeoNix

unread,
Oct 23, 2011, 1:35:13 AM10/23/11
to pon...@googlegroups.com
嗯,谢谢你的评述。其实…… 怎么说呢,C++的位置是个高不攀低不就的东西。说底层吧不如C,高层吧,比他好的更多。

设计方面,也是为什么我多次提到《程序设计实践》这本书,俩老头用马尔科夫链算法的经典例子,描述了最初设计用语言描述各个语言的方式。最终竟然是Perl胜出,而Perl的语法很接近低级语言,可以作为“原型语言”描述,如果需要便可以转化为低级语言。就如何快速接触业务来说Perl也是胜出的。而C语言只在执行效率上胜出。而C++在这个例子面前典型的体现了高不攀低不就。

而最初的那篇我没有说有关执行性能的,通篇只是在说一个用C++习惯的人,用C之后不习惯而发现的一些问题。而我所说的绝大部分都是在说发现的好习惯和坏习惯的一系列问题。析构函数那里,可能我表达有问题,并不是说析构函数的问题,而是代码风格的问题,乱return的问题。只是在不用析构函数之后才发现乱return的难维护,反复测试过明白开口闭口原则,其实适用的地方还是很多的。

可读性方面我不同意你的观点。C比C++要易读,就算如你所说的不易读也可以用lint去检查。而C++是没法用工具帮助你查出隐患的,这也是为什么那么多大牛用正交性原则批评C++的原因。所以有关编码效率的问题,我用C++这么久真的并没有感觉有多么高。所以这点上你说服不了我,呵呵。而我多次看到用程序去生成代码这个很早就出现的言论。而我在用gengetopt的时候,才真的被触动了。

而我上面也提到了,我有理由相信C++的能力。可“如何”最合理的使用C++才是我想讨论的问题,而不是争论C++的毛病。我现在是站在一个代码是否可读,是否易维护,在团队的的协同能力上,怎么指导初学者,怎么杜绝隐患。

为啥别的语言有瓶颈问题就来求C++帮助?拟人化描述,Javascript解析速度遇到问题,我变成C++就好了,而C++去想,我遇到问题我去求谁?谁来帮我?

Linus那里,你看到了,很明显他开始就说的是气话,批评没看代码,但实际上Dmitry Kakurin不但看了,还很仔细的看了。可是后面很明显话糙理不糙。只不过后面的一些项目的问题,他的话给我的触动还是蛮大的。

yuan zhu

unread,
Oct 23, 2011, 1:45:42 AM10/23/11
to pon...@googlegroups.com
这个哥们儿其实就是来哗众的祢衡,你看着吧,他又会新开一堆别的话题等着你来反驳。等你反驳累了,他就实现了“和人交谈要说最后一句话”的目标:“瞧,别人被我驳的哑口无言”。

另外刚才那个结论是有信息论意义的:如果某个压缩算法能够把一个稳定无记忆信源的某些输出序列压缩得小于这个信源的熵,那么这个信源必定存在别的序列输出,被这个压缩算法压缩后大小大于信源的熵。(在压缩算法不知道信源确切输出前,他只能试图去逼近最佳性能;源自渐进均分定理)。很多算法的时空性能分布都可以用这个结论去描述。


On 10/23/11, Shuo Chen <gian...@gmail.com> wrote:

LeeoNix

unread,
Oct 23, 2011, 1:55:11 AM10/23/11
to pon...@googlegroups.com
10多年前的书。其关键之处在这几个字:不可预测的。

>>我们也认为,STL作为C++的一个新部分,仍然受到不成熟实现的损害。在使用STL的不同实现或使用不同数据结构时,导致的性能变化是不可预测的。

10多年的书,我还是那句话:其经典性就是我反复看的一个原因。我有理由相信。

STLport可以用的版本从2006年开始就成为一个值得考验的STL版本。在我上一个公司作的项目就用足够好,用的是4.6的版本。

但性能再提高也并不代表我作为个人研究就相信。说白了我就是为了质疑而质疑,就像我举的菲比对罗斯说的话那样,你就没有一点点质疑的念头?这么多编译器,这么多STL,这么多选择?到底如何做才是最有帮助的。

另外:我说你能不能不要冒出一句来,然后下面有个帮腔的,哇,陈硕大家来了,你涵养真好。

我不是攻击你个人。我是攻击你这个大家的称号和称你为“大家”的这个人,帮腔到底为何帮腔?激发矛盾吗?我可不是为了吵架而来的。

LeeoNix

unread,
Oct 23, 2011, 2:00:56 AM10/23/11
to pon...@googlegroups.com
我发现我有理由再发个邮件向你道歉。

我刚在另外一处发表了对中国所谓权威的质疑,我相信你也看到了。过来就看到有人对你称呼,哇,陈硕大家。

所谓话赶话就是如此,请你原谅。如果你真的是陈硕,那么顶着个大家的称呼相信你也很累了。

毕竟在这里发邮件,不是为了吵架。我早就过了为了吵架在这里消耗时间的年代。

与其吵架打字还不如多看点日剧。


在 2011年10月23日 下午1:33,Shuo Chen <gian...@gmail.com>写道:

风河

unread,
Oct 23, 2011, 2:01:38 AM10/23/11
to pon...@googlegroups.com

他并没有称自己为大家吧。

LeeoNix

unread,
Oct 23, 2011, 2:33:18 AM10/23/11
to pon...@googlegroups.com
有关编码效率的问题,我发现和你有分歧,所以多说一下我的看法。

首先我请你相信我是一个一年内在Windows和Linux都有几千行以上编写C++代码经验的程序员。

说老实话,编码效率,是“写”完代码的效率,还是一段时间“写”完“能用”的代码。这点值得商榷。

用C++或许你写代码写的很快,但是有时候一个很低级的错误,能让你半天摸不着头脑,是很让人气愤的,尤其写代码的不是你。所以这也是我开篇描述那么多习惯的焦点。

有时候,别人写的代码也是如此,说白了无非是编码习惯的问题。可是C++培训的良莠不齐,有时候项目里设立一个编码标准,也不一定能让人读懂。

促使我用CppCheck的一个原因,是有一次,我查了一个晚上的问题,最终发现竟然一个存在与class的变量没有初始化。而这个问题,半小时才可能出现一次。他们好几个人轮番找,最终找不到这个Bug,就找到我。所以我因此奋战了11个小时。找出问题之后,气得我砸桌子砸的手疼,我还不能朝写代码的人发火。

而像CppCheck这样的工具,静态找到的问题,也无非就是变量有没有初始化等等很基础的问题。有些比较复杂的问题,就查不出来了。如果再出现半小时才出现一次的问题,那头疼的不是我了,呵呵,我早就不在了。

静态检查,不知道有没有比CppCheck更好的工具,推荐一下。

后面有代码规范之余,我还在项目里维护了一个Wiki,题目就是,不能干XX,必须干XX,列举了一堆不能干,必须干的事情。出了某个问题我就加上,几个人我都是晚上手把手教必须怎么怎么写。可是怎么总是会出一些问题呢?其实这个一直是我反思的问题。其实这个是当初我们那个团队管理方面的一些问题。

围绕这个我这个WIki所说,组织一些会用C++,但C++技艺没那么好的人。真的有点累。可惜没的选择,只能用C++。

有的时候,某些人移交代码给别人做。然后本人干别的去了。代码风格泾渭分明的看的出来是两个人写的。

我为什么那么反感STL,就是很多人不熟悉STL,写很多使用STL的代码让我感到很无奈。像类似void push( std::set<int> section )这样的代码,当我看到说,为什么不用引用?他说,我看别人这么写,我就这么写了。我只能扶着额头,”勒令“他修改所有类似的代码,这不怪他,用和不用引用的效率是差一个档次的,而这个他不知道怪不得他。

而我在接触C语言代码,我才发现。用工具生成骨架代码,是避免一些问题的一个有效途经。但骨架代码的前提,就是有合适的库和框架支持。

可我到现在,真的不知道有什么更好的途经,能提高编码效率。让普通熟悉的C++程序员能更好的做事,而不需要知道边边角角的东西。


在 2011年10月23日 下午12:28,Yuantai Du <yuant...@gmail.com>写道:

yuan zhu

unread,
Oct 23, 2011, 3:19:48 AM10/23/11
to pon...@googlegroups.com
只是人家年纪比我长,我又读过人家翻译的书,喊老师不好,称呼一句“大方之家”真不知道怎么也能成为你攻击我的靶子呢?

和我开始举的例子一样,你去质疑stl为什么不去质疑C库函数像memmove的实现效率呢?仅仅就是因为STL的源码必须公开在头文件?所谓的为了质疑而质疑,就是专拣软柿子捏?更何况前面(把你提出的问题:std::deque,
ACE, QT)都给你解释了,你还是照样不听,去搬出一堆古书和一堆“专家意见”来说明stl不靠谱。不想把你和那些想靠炒作来出名的人类比。

整天吵嚷语言优劣这些月经贴很无趣的。后生小子最近回学校陪女友,有一些观点希望和大家分享。

把你的idea翻译为代码是一个信息压缩的过程。

有时候你发现繁杂的idea,被X语言轻松的用几行代码表达了出来。这说明这种X语言压缩掉了idea中的某些冗余(这种冗余源自你脑海中使用母语对这个idea的编码过程)。

有时候你发现简单的idea,被Y语言写了上千行代码才表达出来,而且还总觉得犹有未尽之意。这说明Y语言在压缩你的idea的时候性能不佳,并且还有误码(如果你的idea有不能被压缩器表达的部分,我们认为压缩器输出长度为无穷大。比方说用JAVA写驱动,我们认为程序代码无穷长)。

等等,信息学渐进均分性定理告诉我们:任何压缩器把某个稳定无记忆的信源压缩输出的平均长度(再次强调:平均长度)必定是信源的熵。那么这也暗示我们,任何一种语言在用代码表达多个不同的idea时,必然同时存在好的结果与坏的结果(只要考察样本够大)。也就是说,任何语言都有他优与劣的地方。所以客观的从信息学的角度上讲,讨论编程语言的编程效率豪无意义!

但是,这个问题也并不是完全没有意义。好的语言(压缩器)可以:让最常见的idea性能尽可能的好,让性能不好的输出一定源自于不常见甚至无意义的输入idea。所以,我们的库函数啊,类库啊,就像压缩算法里的字典一样,让我们常见的idea编程效率最高。

然而什么是最常见的idea呢?我想这就是出现语言之争的时机了,linus说是内核以及系统设计,有的人说是web开发,有的人说是服务器编程,有的人说是游戏开发,还有的人说是嵌入式。。。。。有的人说某些idea无意义是IT民工才干的事情不值得压缩,有的人说有的idea天生比别的高贵(内核开发人员很常见的想法)压缩效率低也应该。

上面的例子我尽可能纯用数学上的东西来说明,直到最后才提到主观因素。大家真的不觉得语言之争其实很可笑吗?把CSDN的月经贴到处散步,很好玩吗?

如果大家有兴趣,我会继续写如何把软件重用与可记忆信源综合,需求变更与非稳定信源综合,最后给出一些定性的结论。

本来不想搭理,只是别人把指头戳到我脑袋上了。

yuan zhu

unread,
Oct 23, 2011, 3:31:16 AM10/23/11
to pon...@googlegroups.com
这里不讨论强典型集以及误码率的概率收敛问题(不然就太艰深了,不适合在TL这种场合谈),希望信息学达人不要站出来拍我。

LeeoNix

unread,
Oct 23, 2011, 3:35:19 AM10/23/11
to pon...@googlegroups.com
我无意与你吵架,多说一句:我也比你年长。你怎么不尊敬我呢?怎么不称呼我为“大家”呢?

在我眼里,邮件列表都是一个个平等的,可以互相交换信息的网游,没有所谓的大家小家中家。我也不看人的名字资历性别。你带着有色眼镜看陈硕说的话,就已经开始有失偏颇了。特别让我感觉特别异样,他说了一句话,你就吹捧,好有涵养,你这就叫对人“尊重”?

我原帖根本就没提到STL,而是后面扩展说的。况且我就是要质疑STL,是我的实际项目经验给我带来的痛苦而证实的。本来我都没质疑过,而且很久以前我就在TopLanguage说了我另一个朋友质疑STL,当时我还支持STL的帖子,你通过网络搜索到很早的帖子。而我现在竟然和他一样开始质疑了。

另外我“凭什么”不质疑stl而去质疑memmove呢?我在项目里那么多代码一个memmove都没用,但是用到了大量的STL。一个有关STL的问题出来了,我要知道为什么会出问题,为什么?你作的项目,用了STL不出问题,怎么不说说STL的好,而用移花接木的方式说了个memmove让我很是费解。我凭什么要质疑呢?我又没用到memmove。我作为管人的人,很多时候都要手把手的教别人用STL,手把手的教C++不要出这个问题不要出那个问题。以及其他很基础的问题。

我又不是为了玩语言而讨论这个,而是因为实际的工作项目遇到了问题,而我试图通过质疑去反思理解找到解决问题的方案。而不是为了你的信息学和你的喜好去讨论编程,你不想搭理,就别搭理,我也没空和你吵架。

Abioy Sun

unread,
Oct 23, 2011, 3:51:23 AM10/23/11
to pon...@googlegroups.com

语言而已-________-,至于吗?思想才是最重要的。

Lich_Ray

unread,
Oct 23, 2011, 4:00:20 AM10/23/11
to pon...@googlegroups.com
On Sun, Oct 23, 2011 at 2:51 AM, Abioy Sun <abio...@gmail.com> wrote:

语言而已-________-,至于吗?思想才是最重要的。


君不见,很多人的思想已经被语言禁锢了。比方说我认为满地 return 的代码才是好代码,模板接口才叫抽象,因为我的想法多少被 C++ 的特性禁锢了。C 的卫道者们看法就完全相反,至于理由是 C 缺少这些特性还是这样做放之四海都不对,这就只有局外人说的清了。

--
Ray Stinger, nickname Lich_Ray
God is in his heaven, all's right with the world.
-------------------------------------------------
let focus = 'computing' in where:
http://lichray.javaeye.com
let focus = 'computing' in here:
http://let-in.blogspot.com

LeeoNix

unread,
Oct 23, 2011, 4:12:26 AM10/23/11
to pon...@googlegroups.com
而且你说话的口气和方式,跟我以前带的一个年轻人极其类似。

他用stl的vector,我告诫他尽量不要用[]操作符作遍历,用迭代器,

他就大声质疑,既然有这个,为什么要用。

然后他用了,然后不小心越界出问题了。

然后我告诉他,既然你用就用at,不要用[]

他又大声问:既然有这个,为什么不要用。

前后就差一个字,一个是要用,一个是不要用。

听都没听我的话主观的盯着一点就开始反驳的。

我后面还给他说,[]操作符没有越界检查,只有at才有。

然后他继续说,既然有at为什么还要写[],为什么要多加个at?

说白了,最后的纠结的最后还是[]。

我本来想告诉他,加入一个at是有道理的。可是干脆我给他改了代码,后面让他走人。

但他的大声质疑,揪着一点不放。唉,让我挺无奈。

不过让我也不得不反思:怎么能这样,到底是STL的问题还是人的问题。

有时候对于STL无奈的纠结,竟然让我到了有种心理扭曲的程度。

还有使用CEGUI时,用的那个破String的,就算换了std:string我还是害怕一个习惯,不是我用,而是别人用:

类似:winMgr.getWindow("Bag_safe_btn")

而getWindow是 Window * getWindow(const String &name);

如果这么在Render的时候调用getWindow,就悲剧了,彻底悲剧了。

其实经验很简单,在Render前面弄个String类型的变量就没什么大问题了。或者更好的,在Render前就用getWIndow获取Window也是没问题的。

但是可惜啊,我的人,所有的人都有个共同的“常识”就是用引号的常量字符串,他们认为是常量时间,而事实上并非如此。

我有了以上经验,我花了好几天,偷偷的给他们全都修改了,然后在例会里告诉他们不要这么干,不解释任何理由。

后面听说CEGUI加了新的为Render提供的String,可是我们的项目已经没法换新的CEGUI了,我只能小心的更换为STL的string,然后小心翼翼的用。

但我还是很喜欢手下的这些人,性格都很好。他们很踏实,就算不在一起也是很好的朋友,可是总是在这些微小的地方让人纠结。说真的不是他们的错,另外或许是他们的知识不够丰富,

难道是我的错?所以我就试图找谁的错?
我可以形容我自己对于STL的心态是扭曲的。

yuan zhu

unread,
Oct 23, 2011, 4:17:26 AM10/23/11
to pon...@googlegroups.com
“语言不重要,重要的是思想,”这话其实很容易让人误会的,也很容易成为老板忽悠新员工一周学门语言来做不同的项目的理由。这话是老鸟们的总结,而不推荐作为给新人起步语,很容易让人浅尝辄止,一无所获。毕竟思想对新手来说太抽象了,让他们实实在在学到一门语言有时候更有用,能领悟到多少思想那完全是个人的造化了。思想是灌输不了的,如同认为语言之争本质是宗教问题一样。

LeeoNix

unread,
Oct 23, 2011, 4:24:53 AM10/23/11
to pon...@googlegroups.com
没错,我是同意你的观点的。Larry Wall写过一篇有关语言的文章,我认为还是满中肯的,里面还提到中文,哈。

换句话说,学语言的人,不注意就可能被强加了造语言的人的思想和哲学观。就像我们汉语说躺的同义词叫仰卧,而英语却说:lay on back。而英语似乎对back特别注意。

而用Java的人和用Python的人的想法很多时候也不一样。
其纠结之处,你像是在形容躺为面朝上。还是背朝下。

有时候这样的纠结,就像计算机的大端派和小端派一样。

Lee Duhem

unread,
Oct 23, 2011, 4:26:51 AM10/23/11
to pon...@googlegroups.com
再牛逼的思想也需要通過某種語言來表達,語言掌握不到位,談思想也只能是空談而己。

2011/10/23 yuan zhu <zy49...@gmail.com>:

yuan zhu

unread,
Oct 23, 2011, 4:35:07 AM10/23/11
to pon...@googlegroups.com
“你有多少思想,取决于你能表达多少”。援引一句话。
用信息论或者机器学习的看法来讲,这些所谓的思想,其实就是一堆模式(字符)串。要说是设计模式也沾边。

王宁

unread,
Oct 23, 2011, 7:05:26 PM10/23/11
to pon...@googlegroups.com
最近正在重构五年以上历史的服务器端C++代码,有些新的体会。

背景:模块是正在运行的服务器后端的一部分,质量和部署规模都是业界顶级。原作者曾经是顶级的操作系统程序员,C专家。模块修改活跃,五六年间有超过二十人频繁修改和维护,以及大量小更新。提交者的水平肯定高于业界平均。

问题:原作者设计和实现虽然使用C++,但从一开始就混杂了很多C的用法。之后由于各种原因,该模块一直频繁更新,但没有大规模重构或重新设计过。目前,代码质量和效率依旧极高,但新功能开发难度变大,周期变长,bug数量也更多。

观察:相比C++,C用法造成了不少明显的设计问题。

一、资源管理。

C中的资源管理简单高效,但相比C++缺少直观和约束。即:新的代码提交者必须完整正确的理解原作者的资源管理设计,否则极易出错。而C++中实现RAII和ownership相对容易,新的C++书籍和文章对此也比较强调,因此犯原则错误的可能性稍低。

需要注意的是,一个最初看似合理的设计,在多年之后很可能会演化成一个严重的设计问题。

例如,C代码中的资源所有权(ownership)常常不清楚,一定程度上鼓励资源共享和交换。这通常不是一个设计缺陷,而是考虑效率而刻意选择的设计特性。早期系统相对简单并且有原作者开发维护的时候,资源管理并不困难。随着系统复杂度增长和主要原作者离开,资源管理的原始设计变得不清晰,开始被误用。尤其是一些核心数据结构,在不同开发者添加新功能之后,常常会出现不同的资源使用模式,以致费解。一个演示性的例子如下:

vector<Resource*> items;
vector<Resource*> selected_items;

以上两个vector中的部分Resource共享,但假设selected_items一定出现在items中,最终只需要释放items。不久,新功能中,假设被破坏,selected_items可能但不一定从items中产生。最初合理的设计开始变得复杂。

问题看似简单,一旦出现却很难解决。即使重构和重新设计,也需要考虑到生产系统对功能和性能的要求,未必能够允许重新设计和修改(比如使用计数指针)。而之后在原系统中添加新功能则需要彻底理解很多隐含的假设,并且极易出错。

二、缺少封装。C风格代码中的封装更多为了代码复用和数据分组,而非抽象。这其实也是(C风格的)struct和C++中class的本质区别。只封装数据而不包括方法和访问控制会制造不可琢磨的类型,即“知道怎么用,但说不清是什么”。

比如,我们的模块中定义了struct State,存在于整个执行过程,用来保存一些必要的内部状态,以及在不同步骤之间传递信息,并提供共享的工具方法。但随着代码演化出现了几个严重问题:
1、由于缺乏清晰的抽象,State被当成全局变量使用,加入了很多只被部分子模块使用的成员变量。由于缺乏合理的访问控制,往State里加变量成了最方便快捷的做法,大家于是乐此不疲。
2、随着变量的加入,依赖和初始化顺序变得复杂,并且不合理。例如:初始化A -> 使用A -> 初始化B -> 使用A和B。从此,State的各个部分很难再被分离开。
3、自然的,State的角色开始模糊。出于方便,它被作为几乎所有子模块和方法的参数,因为没有人知道怎么正确单独初始化其中部分需要的变量。这样的代码几乎不可理解,因为隐含的依赖大大增加了。

C++中的类,如果合理使用,比C更容易清晰的定义接口和权限,以及角色。不必要的复杂度可以被限制在较小范围内。的确,类可能被滥用,比如:抽象不明确,接口不清晰,无关成员和方法,等。但这些不足以彻底否定合理封装的价值而彻底回到C。问题在语言之外。

三、效率优先。似乎C程序员比C++程序员更加强调效率。一方面,C的执行模型更简单清晰;另一方面,C专家常常积累了大量高效代码的经验。对他们而言,从一开始就写最高效的代码是自然且必须的。但极致的代码往往存在很多设计上的缺陷,它们会随着系统增长而散落各处。

以过程为中心。由于C更贴近底层,C代码或多或少强调过程和执行顺序多过数据和类型,也较少考虑设计模式。顺序代码初看清晰简单,当新功能逐渐加入之后,代码块之间的依赖逐渐增加。不必要的依赖,尤其是隐含的依赖,使代码难以理解和修改。我们的模块中出现了相当长的单个函数,每一个顺序执行的代码块都不复杂,添加新功能也比较简单。但几年之后,大量的变量引用和条件判断使得代码执行逻辑十分复杂。很多变量实际被作为全局变量使用。由于没有人能够理解代码块之间的依赖和交互,调试和重构都变得十分困难。

小结:很多问题,并非C特有,在不良的C++代码中也经常出现。毕竟两种语言本质上等价,也非常相似,各有优劣和用途。我倾向于使用C++,基于以下几点:
1、机制。C++提供了更成熟更现代的抽象和封装机制,更容易实现合理的设计。比如类。C的抽象、封装和访问控制都不完善,即使实现,也远不如C++清晰直观。
2、思维。我接触的C专家多少都偏好序列化和高效的代码。这与教育、书籍和社区都有关。而现代的C++更强调设计和模式。新手从一本较好的C++教材入手能更早更好的接触到设计的思想。
3、业务。使用C实现操作系统几乎无可挑剔,一方面因为效率,另一方面因为数十年来产生了大量的idioms,它们几乎已经成为C语言的一部分。但除此之外,C++的抽象机制更容易解决复杂多变的现实业务问题。
4、人。C简单灵活,也能做出优秀的设计,但很难在代码语法层面表述和限制。后来者只有在充分理解前人设计的基础上才能少犯错误。C++的机制相对便于在语法上表达设计,更重要的是,便于编译器限制和检查后来者违反最初设计的错误。考虑到实际的工程压力和人员流动,C++比C更容易维持好的设计,也更容易扩展新功能。

C++相对于C,容易出现过度设计和技巧滥用。我觉得这是语言之外的问题,应该通过定义规范和缩减特性等工程方法解决,并不是彻底抛弃C++回归C的理由。

2011/10/21 LeeoNix <leeo...@gmail.com>
好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。

我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。

而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给“宠坏”了。

1、变量,该死的变量。

变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要“随意”的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。

我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说“随便”声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。

过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于“静态”检查,现在才明白。很多隐患实际就是坏习惯养成的。

2、析构函数,该死的析构函数。

我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了“随意”二字。其实……惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。

多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了……


Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫“result”的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。

我看到别人转载的Jasone Tee写了一个文章A return to Good Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?

3、思念模板,但忍住不用。

3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The C++ Programming Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。

4、写个库,然后再写个工具去为库服务。

请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c" "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。

我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。

而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。

5、class的封装真的有那么好吗?

Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。

如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。

我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。

Hub Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。

6、干好一件事。

Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。

FIXprotocol设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的FAST协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,这里可以下载看看。我看了这个给我的感觉是,我这些年到底做了些什么,怎么写的代码就没长进?

那什么才是“干好一件事”,还是Hub Scott写那个Stack例子,看完之后曾经和别人争论过Pop要不要返回值的事情。而STL也是这么做的,pop是pop,而top是top,传统介绍栈的描述,遵循了“弹出”这个概念,pop是有返回值。而现在用STL的栈,逐渐都接受了top结合pop的方式。

我继续重新审视以前写的代码。那个所谓封装的D3D的类,其结构严重违反干好一件事的原则,唉,越看越觉得,觉得……真的很难堪。

LeeoNix

unread,
Oct 23, 2011, 9:20:58 PM10/23/11
to pon...@googlegroups.com
第一点,你说的资源问题,我也遇到过,而且遇到了不只一次。

我也感觉这个是与最初大部分学C++的人最初接触C++的时候一开始学的是C的问题,这也是Stroustrup和Andrew说了很久的问题。而C推荐的习惯,在所谓的“效率至上”的借口下,而且没有普遍性的容器的前提下,交互点偏强。并没有像C++那样强调多个容器的独立应用,交互点偏弱。造成了交互这点本身,是受人本身的能力去控制的,或许开始设计的人是个老手,他有自己的习惯去很好的避免了强交互造成的资源同步问题。可后续的人就不一定知道了。而此类错误很难以让人即时察觉,而且用长时间的单元测试和压力测试也不容易找出。

我就说说我最痛苦的一次吧。遇到的情况是内存和显存交互的时候出的问题。其实原理很简单的一个核心模块。管理显存,当显存不够了,就要立即释放显存,数据还给内存。而因为流畅的问题,还要定时释放不用的显存。所以你一说这个问题,我就想到这个例子。唉,想起来真的是痛苦不堪啊。我们做游戏用到的显存管理是一个老手从他其他游戏那里借鉴过来的。一直运行的都很好,而且用这个的游戏运行了好几年也没出问题。但拿到我们这里一年内做项目的时候也没问题,一直都没注意。我印象很深,在游戏内测那天,扔给玩家的时候,就开始频繁报错。当时也是太自信,没有加玩家上传minidump,我近2天2夜期间就没睡多少,查来查去,查到了这里的问题。我只是把他写的几个数据结构修改为list报错就少了很多,加了一个缓冲,仔细修改了线程的同步方式,我以为解决问题了。但在几个月后封测前,我就让写服务器的同事写了个用MySQL保存并提取dmp文件的服务端。而封测那天,从玩家那里传回来的dmp文件,又指向了这个显存和内存交换的地方,虽然不是像第一次出问题那么大面积的问题,但还是存在。之后的2个月,我就是在搞这个东西!我不知道为什么别人用的好好的,而我们用了就出问题。我反复看了版本记录,也没找到根本原因,找了几个随意修改的地方就出问题的地方,但也并不是根本原因。可以说稍稍一触碰就出问题,安全完全没有保证。

第二个问题,是结构依赖的问题,问题很典型,也是新手常常会犯的错误。不过这是代码习惯的问题。但很明显C++在有编写构造析构函数习惯的情况下,可以简单的避免这些低级错误,可以说,一个C++新手和一个C新手在写此类代码。C++新手是会比C新手写此类代码要安全。我同意你说的这个特点:问题在语言之外。

不过针对这个,我还补充一个C++的问题。就是C++的虚函数造成的生成虚表的问题。这点,好像qiaojie兄曾经在以前发过帖讨论过,虚表在什么时候创建的,怎么避免某些人不合理使用造成的虚表被清空的问题。这个很隐含,但我也遇到过。

第三个问题,其实还是和第二个问题一类。我倾向于你对于第二个问题的总结。就我而言,其实是大型系统经验导致的。其实这个有的中国国情的特色,说老实话,起初编写代码的人,都是一些西部牛仔,单枪匹马的干,团队意识薄弱。而中国对于代码会议的组织也偏弱,也因为面子问题或者其他问题,不能踊跃的提出自己遇到的问题,而且程序员的普遍内向,要不就唯我独尊谁都不服,两极分化的不得了。指出自己的错误,指出自己的错误,不仅仅能提高自己也提高大家。

我举个我的例子,隐含的类型转化的问题,有个同事就提到自己的问题,if (有符号数 < 无符号数),这时候,有符号数会隐形的转化为无符号数,这样符号位让有符号数的永远都比无符号数要大。而这个同事比较单纯,很勇敢的把自己的问题说出来,我发现除了我这个什么书都看的人,在C专家编程那里知道了这个问题。而除我之外在场的所有人都不知道这个地方,都以为,应该是可以的。

我组织过几次,其实效果很好,有的时候分配的工作找不到思路也可以大家讨论一下,比如当时写魔法系统的,面对策划的变态条件,不知道如何是好了,大家七嘴八舌的说了一些方案,虽然说可以被采纳的不多,但给他很有效的拓展了思路。还有代码审查的制度并没有建立,没有一个可信的有经验的人去把控提交到核心仓库的代码。

而这点,其实还是你总结的问题,问题在语言之外。

LeeoNix

unread,
Oct 23, 2011, 9:40:22 PM10/23/11
to pon...@googlegroups.com
补充几点:

你说的你接触的C专家,如果说缺少设计思维,不仅仅是你说的几点。还有中国封闭的国情、只在Windows环境开发、还缺乏总结自学能力,也是我为什么在我的文章里哀叹的原因。而C很多代码提供的设计思维一点都不比C++差,而很多地方是C++借鉴过去的。

而自学能力其实也是个很大的问题。而且这个很极端化,有的人因为自学能力强而变得狂妄。而教育的原因因为自学能力弱,想什么东西都要教。我听得很烦的就是,我不懂,你教教我。有时候真的发火了会说:我教你,那谁教我来着?

就上面那个提到有符号问题的同事,也是我上面举void push( std::set<int> section ); 没有用引用问题的同事。他并没有说他的故障的问题而被人嗤笑,因为他的单纯大家都喜欢和他一起玩,玩实况足球,出去打台球什么的。

Yongwei Wu

unread,
Oct 23, 2011, 9:44:37 PM10/23/11
to pon...@googlegroups.com
2011/10/24 LeeoNix <leeo...@gmail.com>:
> 不过针对这个,我还补充一个C++的问题。就是C++的虚函数造成的生成虚表的
> 问题。这点,好像qiaojie兄曾经在以前发过帖讨论过,虚表在什么时候创建
> 的,怎么避免某些人不合理使用造成的虚表被清空的问题。这个很隐含,但我
> 也遇到过。

我不记得这个讨论。但我的印象里,这方面C++里的规则没什么复杂的:一个含
虚函数的类有一张虚表,每个含虚函数的对象里有一个指针指向这张虚表。虚表
应当是全局的,所以我不太理解“虚表清空”这样的问题(野指针?)。

虚继承会更复杂,但我想大部分人都不用吧。我从来没用过。

>
> 第三个问题,其实还是和第二个问题一类。我倾向于你对于第二个问题的总


> 结。就我而言,其实是大型系统经验导致的。其实这个有的中国国情的特色,
> 说老实话,起初编写代码的人,都是一些西部牛仔,单枪匹马的干,团队意识
> 薄弱。而中国对于代码会议的组织也偏弱,也因为面子问题或者其他问题,不
> 能踊跃的提出自己遇到的问题,而且程序员的普遍内向,要不就唯我独尊谁都
> 不服,两极分化的不得了。指出自己的错误,指出自己的错误,不仅仅能提高
> 自己也提高大家。

需要强制推行代码评审。我们的规定是不通过代码评审,只能签入到SVN的分枝
上。

>
> 我举个我的例子,隐含的类型转化的问题,有个同事就提到自己的问题,
> if (有符号数 <无符号数),这时候,有符号数会隐形的转化为无符号数,这
> 样符号位让有符号数的永远都比无符号数要大。而这个同事比较单纯,很勇敢
> 的把自己的问题说出来,我发现除了我这个什么书都看的人,在C专家编程那
> 里知道了这个问题。而除我之外在场的所有人都不知道这个地方,都以为,应
> 该是可以的。

这个正好知道。并不是都向无符号数转,而是往能表达更大正整数的类型转。
int和unsigned short比,结果是转成int比。int和unsigned int,当然是转成
unsigned int。

>
> 我组织过几次,其实效果很好,有的时候分配的工作找不到思路也可以大家讨


> 论一下,比如当时写魔法系统的,面对策划的变态条件,不知道如何是好了,
> 大家七嘴八舌的说了一些方案,虽然说可以被采纳的不多,但给他很有效的拓
> 展了思路。还有代码审查的制度并没有建立,没有一个可信的有经验的人去把
> 控提交到核心仓库的代码。

这才是关键。哪怕是三个臭皮匠一起看,也是好的。

>
> 而这点,其实还是你总结的问题,问题在语言之外。

这就是了。语言之外往往更关键。

--
Wu Yongwei
URL: http://wyw.dcweb.cn/

Mikster.Z

unread,
Oct 23, 2011, 9:45:45 PM10/23/11
to pon...@googlegroups.com
其实你只是在吐槽你的“年轻人”。
对于有的人来说C#和C++或者C或者汇编,做起事情来可能都错误百出。

akirya(坏[其实我不是什么所谓的坏人])

unread,
Oct 23, 2011, 9:54:19 PM10/23/11
to TopLanguage
1、变量,该死的变量。
随意定义变量也没啥不好,函数较长的话,随意定义变量的优势就体现出来。
但是如果一边想一边写代码的时候,充分证明了一个问题,写函数之前没好好规划,没想过。
随意定义变量也变相了纵容这种做法。
如果遇到这样的人,就算规定变量必须声明在函数开始,那么也是一边写,一边往前面添加变量声明。
见过一个函数前面有200多行的变量声明不?遇到这样的函数谁还有心看下去?

2 、析构函数,该死的析构函数。
理由 同 1

3、思念模板,但忍住不用。
再合适的地方使用。C++程序员常犯的错误就是。那个锤子,全世界都是钉子。玩熟了模板,什么地方都想用。

4、写个库,然后再写个工具去为库服务。
这个很赞同。

5、class的封装真的有那么好吗?
理由同3
遇到这种问题通常是没好好设计。


C++给了太多了自由,这种自由又纵容了程序员们。形成了OO流、stl流、模板流等等(参考C++的十大流派)
相比C语言提供语言级别的特性真的很少,所以写出来的代码风格差异比较小,这也是通常说的C程序员更注重流程。

C++程序员要么把C++当成C with class,要么在深入研究特性的路上。
能够解脱语言的禁锢,合理的使用C++的真是太少了。


On 10月21日, 下午11时49分, LeeoNix <leeoni...@gmail.com> wrote:
> 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
> Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给“宠坏”了。
>
> 1、变量,该死的变量。
>
> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要“随意”的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说“随便”声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于“静态”检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> 2、析构函数,该死的析构函数。
>
> 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了“随意”二字。其实……惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
>
> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
> Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了……
>
> Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫“result”的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。
>
> 我看到别人转载的Jasone Tee写了一个文章A return to Good

> Code<http://www.theserverside.com/tip/A-return-to-Good-Code>
> ,看了英文原文才发现CSDN也翻译转载 <http://sd.csdn.net/a/20110323/294448.html>


> 了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> 3、思念模板,但忍住不用。
>
> 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The
> C++ Programming
> Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。
>
> 4、写个库,然后再写个工具去为库服务。
>
> 请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c"
> "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
>
> 我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。
>
> 而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
>
> 5、class的封装真的有那么好吗?
>
> Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
>
> 如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
>
> 我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。
>
> Hub
> Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
> 我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric
> Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。
>
> 6、干好一件事。
>
> Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
> 简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug
> McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。
>

> FIXprotocol <http://www.fixprotocol.org/>设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的
> FAST <http://www.fixprotocol.org/fast>
> 协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,这里<http://www.fixprotocol.org/documents/2317/fastapi-1.0.zip>

LeeoNix

unread,
Oct 23, 2011, 9:58:30 PM10/23/11
to pon...@googlegroups.com
有关封闭的国情的问题,我还是忍不住多说几句。

特例,比如匈牙利命名法。最早的那些程序员,非常非常多的人都用匈牙利命名法,是C语言使用不当的一个残留问题。而匈牙利命名法带来的问题,直接影响了一代编程人员的思维,而与这些人说匈牙利命名法的坏处时候,振振有词的说,没有这个不就乱了?

而我当时很气愤对某个人说,你设立一个变量叫Name,你告诉我还有什么类型可以被Name使用?你不要给我写什么lpszName多四个字母,这算个什么?你给我找一个其他类型的可以叙述Name的?你多四个字母就不叫Name了?还有什么lpPtr,不加lp就不知道是个指针了?

虽然说项目里禁止使用,但早期非常非常多的程序员都是在Windows下,接触Programming Windows而学的C语言编程,而且开源并没有被广为人知,早期的人接触一个完整的系统。因此而产生的对变量的命名表达含糊不堪的坏习惯,影响了整整一代人。

后面接触C++的人多了。写class多了,这个破的匈牙利命名法就几乎没用了。而后来的人,一开始就没接触匈牙利命名法。而我通过观察老的程序员和新的程序员,比较两级分化的一点,被我归咎在匈牙利命名法上。

akirya(坏[其实我不是什么所谓的坏人])

unread,
Oct 23, 2011, 10:08:05 PM10/23/11
to TopLanguage
这点非常赞同你啊

我在上家公司也干过这事请,但似乎大家不领情。该咋办还咋办,出问题了找我,写出来的代码惨不忍睹啊。

> 后面有代码规范之余,我还在项目里维护了一个Wiki,题目就是,不能干XX,必须干XX,列举了一堆不能干,必须干的事情。出了某个问题我就加上,几个人我都是晚上手把手教必须怎么怎么写。可是怎么总是会出一些问题呢?其实这个一直是我反思的问题。其实这个是当初我们那个团队管理方面的一些问题。
>
> 围绕这个我这个WIki所说,组织一些会用C++,但C++技艺没那么好的人。真的有点累。可惜没的选择,只能用C++。

On 10月23日, 下午2时33分, LeeoNix <leeoni...@gmail.com> wrote:
> 有关编码效率的问题,我发现和你有分歧,所以多说一下我的看法。
>
> 首先我请你相信我是一个一年内在Windows和Linux都有几千行以上编写C++代码经验的程序员。
>
> 说老实话,编码效率,是"写"完代码的效率,还是一段时间"写"完"能用"的代码。这点值得商榷。
>
> 用C++或许你写代码写的很快,但是有时候一个很低级的错误,能让你半天摸不着头脑,是很让人气愤的,尤其写代码的不是你。所以这也是我开篇描述那么多习惯的焦点。
>
> 有时候,别人写的代码也是如此,说白了无非是编码习惯的问题。可是C++培训的良莠不齐,有时候项目里设立一个编码标准,也不一定能让人读懂。
>
> 促使我用CppCheck的一个原因,是有一次,我查了一个晚上的问题,最终发现竟然一个存在与class的变量没有初始化。而这个问题,半小时才可能出现一次。他们好几个人轮番找,最终找不到这个Bug,就找到我。所以我因此奋战了11个小时。找出问题之后,气得我砸桌子砸的手疼,我还不能朝写代码的人发火。
>
> 而像CppCheck这样的工具,静态找到的问题,也无非就是变量有没有初始化等等很基础的问题。有些比较复杂的问题,就查不出来了。如果再出现半小时才出现一次的问题,那头疼的不是我了,呵呵,我早就不在了。
>
> 静态检查,不知道有没有比CppCheck更好的工具,推荐一下。
>
> 后面有代码规范之余,我还在项目里维护了一个Wiki,题目就是,不能干XX,必须干XX,列举了一堆不能干,必须干的事情。出了某个问题我就加上,几个人我都是晚上手把手教必须怎么怎么写。可是怎么总是会出一些问题呢?其实这个一直是我反思的问题。其实这个是当初我们那个团队管理方面的一些问题。
>
> 围绕这个我这个WIki所说,组织一些会用C++,但C++技艺没那么好的人。真的有点累。可惜没的选择,只能用C++。
>
> 有的时候,某些人移交代码给别人做。然后本人干别的去了。代码风格泾渭分明的看的出来是两个人写的。
>
> 我为什么那么反感STL,就是很多人不熟悉STL,写很多使用STL的代码让我感到很无奈。像类似void push( std::set<int>
> section
> )这样的代码,当我看到说,为什么不用引用?他说,我看别人这么写,我就这么写了。我只能扶着额头,"勒令"他修改所有类似的代码,这不怪他,用和不用引用的效率是差一个档次的,而这个他不知道怪不得他。
>
> 而我在接触C语言代码,我才发现。用工具生成骨架代码,是避免一些问题的一个有效途经。但骨架代码的前提,就是有合适的库和框架支持。
>
> 可我到现在,真的不知道有什么更好的途经,能提高编码效率。让普通熟悉的C++程序员能更好的做事,而不需要知道边边角角的东西。
>

> 在 2011年10月23日 下午12:28,Yuantai Du <yuantai...@gmail.com>写道:
>
>
>
>
>
>
>
> > 在我们说完C++的缺点之后,我们要说未来的方向是什么----是向高级语言的方向走,还是向低级语言的方向走。


>
> > 你的标题让我感觉你想向低级语言方向走,而你辩论的多数内容,让我感觉是在批判C++的低级性。
>
> > 什么是高级语言的特征?设计特征更向subject
> > domain的内在概念关系靠拢,就是说,更容易概括问题领域的模型,而实现细节揭露得更少。而低级语言呢?更与机器的实现细节相关,因此较难有清晰的设计。
>
> > 你批评的东西,最初的一篇中的弱类型和析构函数都可以照搬过来批评C,不用析构函数,难道用free_pages会更简单吗?应该相反,因为这其实是低级语言的特征之一。
>
> > 如果你批评的是C++的可读性和编程效率,那么你更不应该换成C,因为C的这些缺点更明显。你应该换成高级语言方向,去用Go,
> > scala,或者Scripting language,他们对实现细节的披露更少,对问题模型的概括更好。
>
> > 然后,问题领域的特征与设计的选择息息相关。在OS级别上,除了汇编和C/C++,我极少极少看到任何其他语言;在涉及硬件的应用程序方面,C++占了统治地位;在要求高性能单机运算的金融软件方面,C++占了统治地位;在web
>
> > programming上,人们越来越多地远离C/C++,甚至远离Java;在Hadoop等并行运算方面,函数编程有很大的优越性。所以,语言特性已经在这里了,关键是需求特征。
>
> > 就拿你举的Linus关于git的评论来说吧,"完全是屁话。字符串/内存管理根本无关紧要。"为什么?因为git的问题领域是代码管理,不是操作系统。他还有另一个更早的著名辩论,是关于kernel是否用C++的:
> > 1) the whole C++ exception handling thing is fundamentally broken.
> > It's _especially_ broken for kernels. 2) any compiler or language that
> > likes to hide things like memory allocations behind your back just
> > isn't a good choice for a kernel. 3) you can write object-oriented
> > code (useful for filesystems etc) in C, _without_ the crap that is
> > C++."
> > 在这里,他的第二个抱怨则是内存管理在C++中比在C中难很多。对照关于git的评论你就可以知道,他说的是针对问题领域,不是solution
> > domain。
>
> > 所以,回到你对"编程效率"的质疑上来,批评C++没有问题,但是要知道各个语言之间的不同到底是什么。如果批评的是C++的运行性能,那么C是更好的选择;如果批评的是C++的编程效率,那么C更有可能变得更差。
>

> > 2011/10/22 LeeoNix <leeoni...@gmail.com>:


> > > 看到这里,我很质疑你说的"编程效率"的评价。但我对此不做评价,因为我已经不是面向对象的狂热者了,所谓的面向对象的效率,我这么多年没见有多好过。
>
> > > 说到这里又让我想起Linus的有关git的骂架了。其实Linus在那个有关git骂架里面,开始言辞激烈,后面却说得很中肯。
>
> > > 一句话总结:C++让人没有把心放到业务上。
>
> > Linus为了设计git,甚至用Shell和Perl设计原型,然后逐渐替代这些代码。最初的git确实很不易用,但是git的核心很早就被设计好了,外面的修正为易用就好了。
>
> > 那个骂架过去很久了,git现在很流行。而我越来越看Linus的骂架顺眼了,不是个人崇拜的相信,是经历过之后才感觉Linus其实不管是不是言辞激烈,说的都是真正的技术争论,而且说的中肯。
>
> > 特别Linus批评的,"完全是屁话。字符串/内存管理根本无关紧要。还是去看看源代码吧(我敢打赌你没有看过)。这不是重要的部分,而且也不复杂。唯一真正重要的部分是设计。"
>
> > > 我过了这么久才明白这个。Dmitry
>
> > Kakurin和其他C++程序员一样,还是一个Coder,没有一个跳出去看项目的角度分析业务,看设计,而着眼于这些细节。其实这就是C++程序员的通病,而我作为C++程序员的一员,其实也是如此。而分析业务,设计的能力,和Java程序员比起来,简直让人羞愧,我也曾经作为羞愧的C++程序员一员,去批评Java的效率问题,但Java效率再差也把项目漂亮的搞好了。
>
> > > 程序设计语言无形中影响了人的思维方式。
>
> > > Linus和Dmitry Kakurin说设计,而Dmitry
>
> > Kakurin却在批评git的细节。然后我退一千步,做git的不是Linus,而是其他人,他的技术没有Linus那么牛,但是他很好的完成了git的核心业务,效率再差,也被快速开发为一个产品投放使用了,剩下的就是调优而已。何况Linus亲自操刀。
>
> > > 而实际的项目里,项目带头人唯技术先进的,毁了多少项目。比如我举个实际的例子,不是国外的。
>
> > 阿里巴巴贸易通,以前就是个垃圾技术生成的IM,很多东西没做好实际上是用网页做的,虽然烂但是他快速投放市场了,大家接受这个产品了。而现在淘宝旺旺到阿里旺旺的版本,阿里巴巴在这方面做的很出色。而相比,盛大的圈圈项目,吹了那么久。就我在盛大的那段时间内,整整一年就没看到一个完整的东西出来,就是内部用的版本也是麻烦不断,我很是费解。现在你在世面上还看得到有人在用盛大圈圈吗?
>
> > > 反思啊。所以才艰难的决定就是:不用C++
>

> > > 在 2011年10月23日 上午12:30,Yuantai Du <yuantai...@gmail.com>写道:
>
> > >> C++的优势体现在其运行效率和编程效率的统一上。其他的大多数编程语言,从Smalltalk,java,
> > >> c#到Go,有足够高的编程效率,但是其编译后的运行效率则无法和C++相比,更不用说scripting
>
> > language了。这是由于这些高级语言的设计中,本身就已经包含了很多的masking,所以,在大多数时候,他们编程效率的提高隐含了运行峰值的下降。C++由于保留了C的大多数底层特性,所以保留了足够人工调整运行效率的空间。C语言有足够的运行效率,但是其编程效率比面对对象要差太多了。所以被局限在了底层编程。一个例外是苹果的ObjectiveC,
> > >> 使用了大量的宏来达到面对对象。不知以后objective c 能否扩展到其他领域。
>

> ...
>
> 阅读更多 >>

LeeoNix

unread,
Oct 23, 2011, 10:11:37 PM10/23/11
to pon...@googlegroups.com
嗯,虚表会因为。比如在构造函数写入比较通用的:memset(this, 0, *this);这样的初始化方式被清空。而对于不存在虚表的struct或者class,这个memset是清理的一个比较好的方法。还有一些其他的对于指针操作不当的问题,会指向虚表而造成的虚表改写。反正就是“不正常”的技巧造成的,属于C++独有。

LeeoNix

unread,
Oct 23, 2011, 10:18:55 PM10/23/11
to pon...@googlegroups.com
呵呵,我也见过的。倒没有说200行。比如A星寻路,里面循环很多,需要很多临时变量,我拿到别人写的代码,前面有大概50个变量被声明在了前面,大概有30多行。明明好多都可以写到循环里面的,其实做事极端化就是如此。

其实很惭愧的说,好多就是把“研究”和“工作”没有分开而造成的,我就是这样一个人。把工作中的一个内容当兴趣研究了,而忽略了工作。

redsea

unread,
Oct 23, 2011, 10:42:05 PM10/23/11
to TopLanguage
说得真好 :)

我自己的感觉:
如果要用 C/C++ 开发比较大的项目, 除非整个团队都有相当的经验, 并且稳定性很好, 否则这个项目要么是起步就会出问题, 要么就是做好以后
代码库腐化得非常快.

整个团队都有相当的经验:
可以向代码库中提交代码的人, C/C++ 基本技术要过关, 同时对系统的理解要足够, 否则什么样的乱子都会出, 而这些低级语言出乱子之后,
由于指针, array index 没有检查, 内存管理之类的问题, bug 会隐蔽扩散, 一个初级程序员弄出来的问题, 如果commit 代
码的时候没有检查出来, 混进了代码库, 多半最后可能需要一个资深程序员相当的时间才能解决.

团队稳定性很好:
由于C/C++ 底层库的缺乏, 各家多半都有不少自作的轮子, 这些自做的轮子, 内部很多时候隐藏着很多没有文档化的假设和约定, 更糟糕的时
候, 内部可能还存在一些不一致性, 使用起来需要有很多需要注意的地方, 而且, 很要命, 熟悉了这个系统的程序员, 已经习惯了这些做法, 可能
并没有意识到这些地方的风险性而将这些风险揭示出来.

在这种情况下, 每次新加入一个程序员, 就会带来相当多的风险给代码库引入很多隐患; 如果某一个时刻, 这个项目的老程序员离开了, 整个代码库
就面临极大的风险, 新入的程序员, 在"似乎" 已经搞清楚情况下的编程和重构, 可能已经破坏掉了原有代码的隐式约定, 造成bug 重重, 即使
后来经过辛苦的努力, 清除掉了这些 bug, 但是可能代码库又腐化了一大步.

Java, Python, C# 等语言, 由于基础类库比较齐备, 自造的轮子少很多, 同时处理的问题较高层, 很多时候有现成的框架可以
用, 使用现成的框架, 很多约定就是已经明确定义好了; 加上高层语言限制性较多, 很多时候做什么事情, 大家都用差不多的方法, 陷阱, 隐藏
约定等问题少很多, 团队成员的变化带来的风险也就小了很多.

LeeoNix

unread,
Oct 23, 2011, 10:50:01 PM10/23/11
to pon...@googlegroups.com
怎么说,好多C++的习惯,是与传统的C语言以及其他语言的习惯是不一样的。所以边边角角的你得通过这样那样的地方去知道。

比如上面我提到的那个小伙子。质问方括号的事情,其实我并不讨厌他质问,只是讨厌他说话的口气。我也反思,为什么不敢普遍用方括号?用STL的人知道它不是异常安全的,没有边界判断。但其他语言是普遍接受大量使用方括号的,而且内部有边界检查。

而其他语言的迭代器是隐形的,你可以写,但不太直接用。boost搞了一堆宏去解决,但只是暂时的方案。

比如双引号和单引号字符串的问题,普遍接受的常识是,这就是“常量”,你可以常量时间使用。但string那个可恶的copy constructor,让我又爱又恨。我以前很奇怪,为什么给Vim写C-Support的人,在class模板里,默认把copy constructor弄到private里面,现在实在是明白了。

还有为什么要用引用,我看Stroustrup的《D&E C++》我知道为什么加这个东西,但不是所有人都分得清引用和指针的问题。C++的概念弄的复杂而且混杂。

可以说C++要不你一开始学就学它,要不就别过早学别的。一出问题,我就得当“砖家”。唉。。。累。。。

Shuo Chen

unread,
Oct 23, 2011, 11:06:44 PM10/23/11
to TopLanguage
精彩好文!

> 2011/10/21 LeeoNix <leeoni...@gmail.com>


>
>
>
> > 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> > 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
> > Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> > 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> > 1、变量,该死的变量。
>
> > 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> > 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> > (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> > 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> > 2、析构函数,该死的析构函数。
>

> ...
>
> read more >>

王宁

unread,
Oct 23, 2011, 11:57:11 PM10/23/11
to pon...@googlegroups.com
我没有提到新手的问题,也与中国国情无关。背景中说了,原作者曾经是顶级操作系统程序员,而所有参与模块维护和提交的,即使是新人,也远高于国内的平均水平。编码规范、单元测试、代码审查和性能测试的执行都极其严格。即使我部分同意你关于新人和国情的看法,我的描述和结论完全不能支持你的论断。抱歉。

补充我的结论:问题在语言之外,并且与个人水平关系不大,毕竟很少有团队能保持五年以上的核心稳定。C++比C能够解决更多语言层面的问题,但测试、集成、文档、定期重构等工程因素恐怕更加重要。

至于是否应该从一开始就着重于“优秀”的设计,还是任其演化逐渐完善,我暂时没有结论,但倾向于后者。

2011/10/23 LeeoNix <leeo...@gmail.com>

jinhu wang

unread,
Oct 24, 2011, 1:00:59 AM10/24/11
to pon...@googlegroups.com
先拍几块砖:
  • 一年几千行的产出放在嵌入式上也就将就了,放在windows上或linux上的应用程序还是不说出来为妙。
  • 命名,一个总是直接用name命名变量的程序员,定是没有遭遇过兼容带来的问题。
  • 关于c++的虚表,估计你还没有本事去破坏一张虚表,你只是破坏了你实例化的对象里的vptr而已。
  • 关于方括号的使用,将异常作为救命稻草的人很难理解到方括号带来的易读易用易维护
  • 关于不用memmove,那是因为你用的库把memmove包装了了一层。

Yongwei Wu

unread,
Oct 24, 2011, 1:08:03 AM10/24/11
to pon...@googlegroups.com
编码规范,代码评审。

函数长度应尽量不超过50行,超过200行需要组长批准。一次评审代码长度不超过400行。

2011/10/24 akirya(坏[其实我不是什么所谓的坏人]) <aki...@gmail.com>:


> 1、变量,该死的变量。
> 随意定义变量也没啥不好,函数较长的话,随意定义变量的优势就体现出来。
> 但是如果一边想一边写代码的时候,充分证明了一个问题,写函数之前没好好规划,没想过。
> 随意定义变量也变相了纵容这种做法。
> 如果遇到这样的人,就算规定变量必须声明在函数开始,那么也是一边写,一边往前面添加变量声明。
> 见过一个函数前面有200多行的变量声明不?遇到这样的函数谁还有心看下去?
>
> 2 、析构函数,该死的析构函数。
> 理由 同 1
>
> 3、思念模板,但忍住不用。
> 再合适的地方使用。C++程序员常犯的错误就是。那个锤子,全世界都是钉子。玩熟了模板,什么地方都想用。
>
> 4、写个库,然后再写个工具去为库服务。
> 这个很赞同。
>
> 5、class的封装真的有那么好吗?
> 理由同3
> 遇到这种问题通常是没好好设计。
>
>
> C++给了太多了自由,这种自由又纵容了程序员们。形成了OO流、stl流、模板流等等(参考C++的十大流派)
> 相比C语言提供语言级别的特性真的很少,所以写出来的代码风格差异比较小,这也是通常说的C程序员更注重流程。
>
> C++程序员要么把C++当成C with class,要么在深入研究特性的路上。
> 能够解脱语言的禁锢,合理的使用C++的真是太少了。

--

Yongwei Wu

unread,
Oct 24, 2011, 1:12:17 AM10/24/11
to pon...@googlegroups.com
这是把C里面的“良好”代码习惯错误地带进了C++……唉,这实际上在代码评审
中是很容易被发现的问题。

2011/10/24 LeeoNix <leeo...@gmail.com>:


> 嗯,虚表会因为。比如在构造函数写入比较通用的:memset(this, 0,
> *this);这样的初始化方式被清空。而对于不存在虚表的struct或者class,这
> 个memset是清理的一个比较好的方法。还有一些其他的对于指针操作不当的问
> 题,会指向虚表而造成的虚表改写。反正就是“不正常”的技巧造成的,属于
> C++独有。

--

jinhu wang

unread,
Oct 24, 2011, 1:45:42 AM10/24/11
to pon...@googlegroups.com
曾经用过一段时间Objective C,就Obj-c本身而言,我的感觉是它更像是封装在c之上的一个小平台,可以类比到MFC、Rose RT等平台式工具性软件。在c的基础上添加了新概念,语法风格更像是通信设备上的命令行脚本。

在 2011年10月22日 上午12:15,HaoPeiQiang <HaoPe...@gmail.com>写道:
所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。


2011/10/21 LeeoNix <leeo...@gmail.com>
好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。

我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。

而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给“宠坏”了。

1、变量,该死的变量。

变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要“随意”的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。

我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说“随便”声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。

过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于“静态”检查,现在才明白。很多隐患实际就是坏习惯养成的。

2、析构函数,该死的析构函数。

我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了“随意”二字。其实……惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。

多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了……


Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫“result”的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。

我看到别人转载的Jasone Tee写了一个文章A return to Good Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?

3、思念模板,但忍住不用。

3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The C++ Programming Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。

4、写个库,然后再写个工具去为库服务。

请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c" "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。

我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。

而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。

5、class的封装真的有那么好吗?

Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。

如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。

我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。

Hub Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。

6、干好一件事。

Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。

FIXprotocol设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的FAST协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,这里可以下载看看。我看了这个给我的感觉是,我这些年到底做了些什么,怎么写的代码就没长进?

那什么才是“干好一件事”,还是Hub Scott写那个Stack例子,看完之后曾经和别人争论过Pop要不要返回值的事情。而STL也是这么做的,pop是pop,而top是top,传统介绍栈的描述,遵循了“弹出”这个概念,pop是有返回值。而现在用STL的栈,逐渐都接受了top结合pop的方式。

我继续重新审视以前写的代码。那个所谓封装的D3D的类,其结构严重违反干好一件事的原则,唉,越看越觉得,觉得……真的很难堪。

而干好一件事,和简单性。真的没个真正的标准,我还只是凭感觉判断。

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

说到这里,没多少可说的了。C++的危险就是太多概念,太多“方便”的东西提供。优点和缺点并存。

Brain Kernighan和Rob Pike的《程序设计实践》真的是一本太好的书了,被我看了不知道多少遍了。在书里,一章提供CSV文件读写的代码里,他们用C++写了一个读写类。而且书里面介绍了C++比C语言优势的地方。《Hackers Delight》这本书开始就说,用C++而像用C一样。

坚持让自己用纯粹C语言的时候,我不断审视我以前用C++的问题所在。所谓OOP能一统天下的理论,还有被吹捧上了天的设计模式。这些年在中国被宣传的天花乱坠。虽然说OOP(OOD)还有设计模式我用的很熟,但该是被浇冷水的时候了。

写到这里,我的脸皮到早就没了,呵呵,欢迎拍砖。


akirya(坏[其实我不是什么所谓的坏人])

unread,
Oct 24, 2011, 1:58:09 AM10/24/11
to TopLanguage
评审只是没办法的办法,总有人不遵守规则。
就算能执行下去一个函数不超过50行,那么也很有可能看到支离破碎的N个50行的函数,理解起来还得合并起来理解。
归根结底就是没好的习惯,想到哪里写到哪里,出了问题头痛医头,脚痛医脚。反正最后能用了就行。

新到一个公司,碰到一堆烂代码。要么继续烂下去,要么重构。
不过可惜的是重构在时间面前总是过于渺小,所以只好继续更加烂下去了,直到忍受不了了辞职。接下来接手的人也只好继续烂下去了。
同样的代码向好的地方维护很难,但想烂的地方维护很容易。再加上C++新手不友好的特性,再好的代码也能烂下去。

所以说嘛,最好的解决方案就是用C,或者严格限定只能使用哪用特性。同时做好培训,让团队中人员水平相当。

Yongwei Wu

unread,
Oct 24, 2011, 3:22:28 AM10/24/11
to pon...@googlegroups.com
不同意。

事实上,有人说,只要存在代码评审,代码的质量就会上一个台阶。毕竟,人都需要肯定,不希望给别人看问题多多的代码。

Zhangming Niu

unread,
Oct 24, 2011, 3:34:06 AM10/24/11
to pon...@googlegroups.com
endless discussions..
I would say the assembly is the best, then c, thereafter c++.
then how many programmers could master the language itself? how many days would a project cost?
It runs into the issues mentioned in <<The Mythical Man-Month>>

2011/10/24 Yongwei Wu <wuyo...@gmail.com>



--
--------------------------------------------------------------------
Best Regards,

Zhangming Niu




LeeoNix

unread,
Oct 24, 2011, 5:52:14 AM10/24/11
to pon...@googlegroups.com
因为我已经不参与太多编码了,而且我不仅仅用C/C++,而且作为管人的人,我也参与各类业务类编码很少了。

我一点都不惭愧说几千行这句话。而且我希望比这个数更少,如果我的代码能从2万行降低到6000行,我会非常满意。

而且我还在用Lua,Python,还有一些Perl写Shell和批处理,这些还只有我干。倒是Makefile是别人写不属于我管,后来被CMake替换冗长的手写Make,还用了好长时间的ActionScript。

我总是用name命名,而且很多。而从来都没遇到过你说的兼容问题。

LeeoNix

unread,
Oct 24, 2011, 5:55:08 AM10/24/11
to pon...@googlegroups.com
针对你的我再补充。由于因为有内存问题的残酷经历。我坚决让C/C++的代码使用偏向,转向Python或者Lua。

如果我发现我年用C++代码降到2000行以下,甚至不写了。我会更开心。

LeeoNix

unread,
Oct 24, 2011, 5:59:34 AM10/24/11
to pon...@googlegroups.com
但是这个方法对于某些结构是很易用的,比如我们的定点缓冲,还有好几个绘制的结构,都是这样,在memset被优化的情况下,效率会高,而这地方追求效率,还是有理由的。但这仅仅是个效率特例。唉。。。

而且用memset不会遗忘你加了变量而没初始化为空。

唉,其实对于这个清理内存的,给我的感觉是一半一半的评价。

其实我应该对内存管理弄更好的方法就可能,仅仅是可能不会出未初始化的问题。

问题就是在于这个问题出现的几率不高,只是属于一个特殊问题存在。

LeeoNix

unread,
Oct 24, 2011, 6:17:32 AM10/24/11
to pon...@googlegroups.com
唉,我很赞成你的观点。毕竟人的心理是状态是不好把控的。

其实你们看,我有很多话是很理想主义的,我比较乐观,总是把事情往好处想。

而实际操作不是这样。人有时候是很轻浮的,如果你代码出错,同事有时候见面打招呼:水哥,你今天又出错了。
然后这句话可能被玩笑着说一个多于。有些人,比如我说的水哥,他的承受能力就不错,大家玩笑的说出错,一起做事。
这句“水哥,你今天又出错了。”,在现实里,被说了足足有两个多月。

可是有些人神经脆弱,开不起玩笑,如果你3天说同一个玩笑给他,他可能就炸刺了。。。

另外一个,就是和绩效挂钩。我其实很反对他们把出错和绩效挂钩这个,可惜我没法真正参与决策。我只能相对的保护他们。
特别这个,唉……绩效挂钩是双刃剑啊。而我个人认为,

Royee Liu

unread,
Oct 24, 2011, 7:26:34 AM10/24/11
to pon...@googlegroups.com
不同意第一点,评审是简单易行却又非常有效的办法,用会议的形式大家一起评,有讨论和互动会更有效果,对新手的成长帮助非常大,每周搞一两次两三周就可以见效,如果有人两三个月还不长进把他开掉好了,没潜力。

同意第二点,强制要求函数长短没任何效果,把一个长函数拆成N个一次性使用的短函数只把逻辑打的更散更乱看着费解改着麻烦。

用C不是解决办法,菜鸟程序员用C写的代码更难看。

LeeoNix

unread,
Oct 24, 2011, 8:12:19 AM10/24/11
to pon...@googlegroups.com
语言方面。我想其实争论意义并不大,有的时候个人历程决定了喜好,而且阶段性的总结也会不一样。
就新手来说,就我的个人经历和项目经历而言,我支持你的观点。
C++对新手相比其实比C更容易把控。关键是C++教学的问题,也是Andrew一而再、再而三提到的C++一直存在的问题。
怕就怕一开是学C而后面听别人的话去用了C++。

LeeoNix

unread,
Oct 24, 2011, 8:22:47 AM10/24/11
to pon...@googlegroups.com
嗯,我非常赞成你说的团队“稳定”的要点,其实水平问题只处在那个牛仔单打独斗的年代。而今是能否在合适的位置用到合适的人,而团队人员间的知根知底的配合更是关键。

你最后一句话点出了重点。开始我也是倾向于优秀设计派的。随着做事越来越多,接触的东西越来越多。所谓的一开始就设计好,虽然说很难定位是一句空话。也不是一朝一夕的经验能够把基础能够做好。而我经验不足的时候,误解了框架的定义是“一成不变”,而其实框架是为了适应更多的变化才称之为框架。

Yongwei Wu

unread,
Oct 24, 2011, 10:21:10 AM10/24/11
to pon...@googlegroups.com
你试试看就知道了,把长函数拆短绝不是件容易的事情,也绝不会让代码更难懂。在C里更是难做好。

重构里有一条,可以把长的函数变成一个类,把函数里面的本地变量变成类成员。我试过一次,效果出乎意料的好。不仅代码的可读性得到了提高(没人会让类的成员叫a、b、m、n吧),测下来居然性能也提高了。后者尤其让我惊讶。

手段是有目的的。简单看来,把函数拆短可能可以等价为一样糟糕的代码。但从人性的角度来看,在函数里传大量的参数、或者使用糟糕的类成员名字,都是稍微聪明一些的程序员就不会做的。如果有谁看着这样的编码规范,硬要写出带20个参数的函数来,那还是请他回家的好。

2011/10/24 Royee Liu <roye...@gmail.com>:


> 不同意第一点,评审是简单易行却又非常有效的办法,用会议的形式大家一起评,有讨论和互动会更有效果,对新手的成长帮助非常大,每周搞一两次两三周就可以见效,如果有人两三个月还不长进把他开掉好了,没潜力。
> 同意第二点,强制要求函数长短没任何效果,把一个长函数拆成N个一次性使用的短函数只把逻辑打的更散更乱看着费解改着麻烦。
> 用C不是解决办法,菜鸟程序员用C写的代码更难看。
>
> 在 2011年10月24日 下午1:58,akirya(坏[其实我不是什么所谓的坏人]) <aki...@gmail.com>写道:
>>
>> 评审只是没办法的办法,总有人不遵守规则。
>> 就算能执行下去一个函数不超过50行,那么也很有可能看到支离破碎的N个50行的函数,理解起来还得合并起来理解。
>> 归根结底就是没好的习惯,想到哪里写到哪里,出了问题头痛医头,脚痛医脚。反正最后能用了就行。
>>
>> 新到一个公司,碰到一堆烂代码。要么继续烂下去,要么重构。
>> 不过可惜的是重构在时间面前总是过于渺小,所以只好继续更加烂下去了,直到忍受不了了辞职。接下来接手的人也只好继续烂下去了。
>> 同样的代码向好的地方维护很难,但想烂的地方维护很容易。再加上C++新手不友好的特性,再好的代码也能烂下去。
>>
>> 所以说嘛,最好的解决方案就是用C,或者严格限定只能使用哪用特性。同时做好培训,让团队中人员水平相当。

Zhangming Niu

unread,
Oct 24, 2011, 10:25:35 AM10/24/11
to pon...@googlegroups.com
Yongwei Wu:

在C里更是难做好 + 可以把长的函数变成一个类 => not pure c code.

2011/10/24 Yongwei Wu <wuyo...@gmail.com>

sagasw

unread,
Oct 24, 2011, 10:26:40 AM10/24/11
to pon...@googlegroups.com
我code review时,也是赞同长函数变短,抽取;另外一个是把函数压扁,减少tab层次。
上个月写了篇code review相关博客
http://sunxiunan.com/?p=1929

------------------------------------------
blog: http://sunxiunan.com/
C++, Lua, living in Dalian
http://twitter.com/sagasw
------------------------------------------


2011/10/24 Yongwei Wu <wuyo...@gmail.com>

Zhangming Niu

unread,
Oct 24, 2011, 10:29:43 AM10/24/11
to pon...@googlegroups.com
Sagasw:

代码美感
a) 不能有嵌套的if-for-switch-while出现
b) 不能有非常复杂的条件判断表达式(用于if-while之类)
c) 足够的注释,对于复杂操作,对于条件判断,可以注释。尽量让代码自己说明自己。
d) 如果代码不能在短时间内理解,或者稍作解释就可以理解,应该看看能否有更简洁的方式
e) 函数不要过长,不能超过一屏显示,最多不应该超过2-3屏。
f)经常问自己是否有更好的办法,更简洁明了的代码形势
g) 一个函数只做一件事,如果需要多个功能,再写一个
h) 少用boolean 作为参数切换功能,用withXXXcase, usingXXXcondition函数名字来自说明。道理同g)
i) 少用重载功能,没必要类似函数用一个名字,既然有不同函数实现,那么应该有不同条件描述,可参考h)的命名
j) 抽象层次不要过多,不要过早和过多考虑设计模式/抽象/抽取通用功能这些事情,这些在代码重构阶段可以修改调整

hard to achieve,
one question how to avoid using if for switch-while?

2011/10/24 sagasw <sag...@gmail.com>

Yongwei Wu

unread,
Oct 24, 2011, 10:31:13 AM10/24/11
to pon...@googlegroups.com
是的。C里面更有挑战,初学者可能无法做出良好的设计来做到短的函数设计。

所以我是赞成楼主说尽量多用Python这样的高级语言的,但不敢苟同回到C。用C写出高效且容易维护的代码,事实上对功力的要求极高。虽然不像C++一样需要语言层面的多年学习,但需要很强的设计能力。如果团队里没有很强的架构师能够在函数接口层面给出指导,还是免了吧。

2011/10/24 Zhangming Niu <niuzha...@gmail.com>:

sagasw

unread,
Oct 24, 2011, 10:37:16 AM10/24/11
to pon...@googlegroups.com
写的太简略,主要是给自己备忘的。

a)的意思是循环中有条件,条件里有循环,

____ if something
________ for (xxx )
____________ while (yyy)
________________switch ()
____________________case 1:
________________________for (mmm )

所谓压扁tab,就是减少嵌套层次,尽量让for while switch if靠近左边

 
------------------------------------------
blog: http://sunxiunan.com/
C++, Lua, living in Dalian
http://twitter.com/sagasw
------------------------------------------


2011/10/24 Zhangming Niu <niuzha...@gmail.com>

Neuron Teckid

unread,
Oct 24, 2011, 11:03:22 AM10/24/11
to TopLanguage
C 和 C++ 只不过是两门名字很像的语言, 值得这么扯到一起骂么.

C 的问题在于语言功能实在是弱得捶地, 说白了就是一无所有. 没办法, 复杂只能靠简单堆起来, 看看标准库里面 qsort 这货, 一个排序算
法的接口可以搞成这个鬼样子, 这让开发者怎么下手呢? 尤其又不支持嵌套函数, 所以凡是这种要用到 functor 的地方, 无论多么简单一次性
的 functor, 都得先另求一块风水宝地去定义一个 (有名字, 搞不好会污染全局空间的) 函数, 然后再来用着. 这只是一个小例子, 其它
需要一些现代流行的特性, 亦是悲剧得让人恨不得喊爹, 再比如多态, Python 解释器里面有个 PyEval_EvalFrameEx, 这东
西如果能有个多态 (就算是 C++ 虚表这么虚的东西) 支持一下, 这一个函数里的代码也不至于多得变态吧.

C 的优点在于它真的够简单, 瞧 C Programming Language 薄称那样, 还没有一本 Linux API 厚, 都不好意思拿
出去卖钱了. 基本上有脑程序员学会指针就可以写得风生水起了, 至于漏内存漏文件句柄啥的, 耗点体力总是能查出来的, 一个人查不出来还有同僚审议
呢.

C++ 除了出笔试题之外, 还可以作一般开发之用, 这确实是当代编程语言中为数不多的好东西. 有心看一下 C++ 标准一路的发展就知道, 标委
会那帮宅男根本不介意 C++ 程序员 (或者 C 程序员++) 怎么去骂它们, C++ 这东西其实整个就是一语言特性瞎掰实验室, 像
RAII 这种高级货, 用 C 还没玩过吧; 还有最新进来的 rvalue reference, 不用 C++ 的怎么可能体会到被复制构造虐了
十几年然后像从性奴地牢重获新生的这种感觉呢; 等等. 反正特性在那里, 至于你们用不用, 反正最后投票通过被加入标准就行了.

确实, C++ 特性太多, 屠龙之技已有不少, 不过多也不能算问题吧, 况且标准也说了, 眼不见, 心不烦, 运行效率也不受拖累. 只不过
呢, 有些程序员是见不得其它程序员这样那样, 这应该是团队合作的部分, 算是 leader 的职责吧.

话说, 现代编程语言要是没有垃圾回收, 封装, 多态这三件神器, 还真的不好意思拿出来显摆. 对于 C 而言, 这三个特性的解决方案分别是人
肉, 人肉, 人肉. 对于 C++ 呢, 分别是 RAII, OOP, OOP. RAII 也算是独树一帜的好方法吧 (当然 C++ 甚至连
RAII 都不是强求的, 比如 Qt 就是用的树形关系模型来管理对象的), 而且还能隐藏对象状态临界点, 写一些文件之类的资源操作代码要简洁许
多.

至于 OOP, 真算是槽点爆表的设计方式, 尤其对于 C++ 这货来说. 本来 C 系列语言分离头文件和 c(pp) 文件目的之一是为了解耦
ABI, C++ 用上 OOP 结果又给耦回去了, 这一来让搞动态库的厂商纷纷不高兴了, 以前 C 里面函数都只有声明, struct 给个前
置声明也中, 成员访问都做成 setter getter 就行了; 可 C++ 不行啊, 这 class 前置一声明, 虚表不就玩完了么, 可
是整个的把 class 丢在头文件里面, 成员顺序也不能改了, 虚函数也不能随便加了, 这还好意思谈扩展性? 于是一些奇怪的方法陆续登场, 比
如 Qt 就用了 private implement 来搞, 看起来还有模有样的, 幸好如此, 否则靠 LGPL 养着的企业还不都得回家卖烧饼
去了.

说到 ABI 那毫无疑问是 C++ 的一道坎 (这当然也是标委会不负责任的表现之一, 连 STL 算法的时间复杂度都要规定, 却把这么重要的实
践需求忽略了, 学院派嘴脸一览无余), 这一扯就得扯到 C++ 两道靓丽的风景线: STL 和 boost. 这俩家伙且不说类成员什么的, 连
函数实现都不得不给丢进头文件了. 这下就不得了了, 敢在动态库接口上锚一个泛型容器? 哼哼, 只要其它机器上的库实现有一丁点不一样, 立马崩给
你看.

所以 C++ 在这种三不管的地方还是不要贸然使用的好. 学习一门语言呢, 能用上当然好, 能不上呢也不能强求, 最重要的是体会一下其中的思
想, 然后仰角 45 度看看天空, 挺好的.

It is loading more messages.
0 new messages