C++信徒的摩西十戒

2016-02-19 15:56 8 1 收藏

给自己一点时间接受自己,爱自己,趁着下午茶的时间来学习图老师推荐的C++信徒的摩西十戒,过去的都会过去,迎接崭新的开始,释放更美好的自己。

【 tulaoshi.com - 编程语言 】


  这是C++信徒的摩西十戒,虽然说的是十戒,实际上有十四条,但这十四条都值得将其铭刻在显示器的边缘,供C++程序员们每日膜拜。我要将其铭刻在我的blog里,铭刻在我的记忆里,直到它们成为我思维的一部分。
  
  第0条:不要拘泥于细节(了解哪些东西不应该标准化)
  
  ·缩进:不必规定如何缩进,每个人遵从一个自己喜欢的规则即可。
  
  ·行长:今天已经没有太大的必要限制80个字符了,当然,越有利于阅读越好。
  
  ·命名:不要太严苛,除了宏应该全部大写外,别的只要遵从某种大家接受的风格即可。常见的风格有2种,一种是连字符连接全部小写的单词,另一种是单词首字母大写。假如需要使用各种第三方库,基本上很难保持一种风格。在一定的范围内保持一致,目标是使得阅读更轻易即可。
  
  ·注释:不要规定注释的格式。不过,使用doxygen语法的注释是个好主意,我一直用doxygen产生文档。
  
  ·匈牙利记法:很兴奋,我为自己厌恶的东西找到了支持我的同盟军。在C++语言中借助一点小伎俩来表达类型是无益的,C++压根就不需要这些,它只会带来混乱。
  
  ·单入口单出口:在支持异常和确定性析构的C++世界,这是多余的。
  
  在这里,旗帜鲜明地反对了两样东西:匈牙利记法和单入单出原则。
  
  第1条:在高警告级别干净利落地编译
  
  把编译器的警告级别开到最大,并且能够悄无声息地生成结果。对于那种视警告如无物的人,关门!放狗!也不要轻易的在源代码中关闭编译器警告。
  
  ·对于第三方库,在包含文件四周加以屏蔽即可。
  
  ·未使用参数:不提供该参数名称即可。
  
  ·未使用的变量:插入一个该变量的表达式即可。这算是一个惯用法了,会比较多的用到。
  
  ·变量未初始化:初始化。需要通过一个过程来初始化的例外,即形如:obj; init_obj(obj);
  
  ·某些分支没有return返回值。在这些分支上加入断言:assert(false);再接一个return返回值。
  
  ·有、无符号不匹配。假如无法避免,预先写好强制转换。个人认为,尽量避免无符号数,即使是处理理论上就没有符号的数据,有符号数适应性更好。几乎没有必要使用无符号数---除了某些位操作。
  
  第2条:使用自动构建系统
  
  这个就是DailyBuild嘛!对一个团队项目而言,DailyBuild就是心跳,它应该可以通过一个按钮或是一条命令就能构建出整个系统。您的心跳正常吗?这里的要害是:只要一个操作就能完成所有工作。
  
  第3条:使用版本控制系统
  
  还有那个团队没有使用vcs?假如没有,“盲人骑瞎马,夜半临深池”,真是极好的写照。
  
  第4条:在代码审查上投入
  
  很多团队其实是没有有效的代码审查的。亮出自己的代码,阅读别人的代码,这也是熟悉整个项目的好方法。把代码投影在墙上,几个人坐下来一起评论也是有效的方法。
  
  第5条:一个实体应该只有一个紧凑的职责
  
  单一职责原则。这个原则并不那么轻易执行,即使是STL这样的程序库,也一样会犯违反该原则的错误。在这里,举了两个违反这一原则的闻名实现:realloc和stl 中的basic_string。不过,对于basic_string,我想比起MFC中的CString还是好了不少。在《Exceptional C++ style》中,对basic_string作了剖析,并且得出一个普遍的原则:尽量将函数实现为独立的函数而不是成员函数。
  
  尝试用一句话来说明一个模块的功能,既不多,也不少。假如无法用这样的一句话加以概括,那么重新考虑规划该模块的职责。 第6条:正确、简单和清楚第一
  
  简单的说,坚持KISS原则:正确优于速度,简单优于复杂,清楚优于机巧,安全优于不安全。
  
  ·程序必须为阅读它的人编写,只是顺便用于机器执行 * 编写程序应该以人为本,计算机第二。
  
  ·计算机系统中最便宜、最快速、最可靠的组件都还不存在。
  
  ·......简单设计的重要性怎么强调也不过分。
  
  ·使一个正确的程序变快,比使一个快速的程序正确要轻易的多。
  
  ·避免使用程序设计语言的冷僻特性,应该使用最简单的有效技术。
  
  ·不要毫无节制地重载运算符。
  
  ·不要滥用匿名变量,合理使用命名变量。当然,这不是说连vector().swap(other)这样的惯用法也要排斥。
  
  ·重构技术是改善代码可读性的有效手段。
  
  第7条:编程中应知道何时和如何考虑可伸缩性
  
  从字面上来看,这差不多等于外交辞令。答案无非是“适当的”时候“适当地”考虑可伸缩性。这非常依靠于软件工程师的经验和知识。所以,本条目也“适当地”回避了那种缺乏营养的教导,着重讨论算法复杂度的选择问题。
  
  基本上,线性复杂度可以作为一个算法是否可选的分界点。值得花费精力避免选择差于线性复杂度的算法,而不差于线性复杂度的算法则可以接受。所以,把性能放在嘴边的兄弟们注重了,你的精力可别放错了地方,高德纳言犹在耳:不成熟的优化是程序设计中的万恶之源。必要时,先努力优化复杂度(选择好的算法----算法无用论者,去面壁!)。
  
  顺便提一句排序算法,通用排序算法的复杂度最好是O(NlgN),但是特定领域完全可以有更好复杂度的算法。
  
  第8条:不要进行不成熟的优化
  
  “不成熟的优化是程序设计中的万恶之源” ----高德纳引用的这句话这本书中出现了若干次,高德纳在他的不朽名著《计算机程序设计艺术》中也一再强调了这一点,还说他以前程序中的许多错误都是关于不成熟优化的。看来,唯一在诱惑面前没有堕落的,只有耶稣,即使是大师也无法抗拒。既然如此,建议把下面的话放在电脑桌面上: 让一个正确的程序更快速,
  
  比让一个快速的程序正确,要轻易的太多太多。
  
  第9条:不要进行不成熟的劣化
  
  什么是不成熟的劣化呢?典型的有:
  
  ·在可以通过引用传递的时候,却定义了通过值传递参数。
  
  ·在使用前缀++操作符很适合的场合,却使用后缀版本。
  
  ·在构造函数中使用赋值操作而不是初始化列表。
  
  关于第一条有一些例外,一般而言,不建议传递原生类型的引用(讨论前提是传值的程序语义没有问题)。关于第二条,一些很老的C语言的书上有过后缀版本可能比前缀版本更快----当然,这只可能针对原生类型--的说法,忘记它吧,现代编译器会轻而易举的优化掉这之间的差异。而对于用户定义类型,实现后缀形式的++和--操作符都意味着效率上的损失。习惯的力量是巨大的,养成使用前缀版本的习惯吧。
  然而,要区别不成熟的优化和不成熟的劣化之间,需要足够的练习和基础知识,这些知识可以从《Effective C++》,《More Effective C++》《Exceptional C++》《More Exceptional C++》中获得。
  
  第10条:尽量减少全局和共享数据
  
  全局数据是应该努力避免的,它导致两个问题:名字污染和远程耦合。类的公有静态变量只是解决了名字污染问题,并没有解决远程数据耦合问题。同样,Singleton模式也存在远程耦合问题。
  
  全局数据通常就意味着共享,共享数据则意味着关系,意味着复杂性。再多线程中,对共享数据的访问通常都需要串行化。
  关于变量,一个比较深刻的看法是:一个算法使用的变量(命名的和匿名的)越少,就越好。这个变量包括局部变量。
  
  第11条:信息隐藏
  
  对于一个类,决不要将数据公开(数值聚合的strUCt 例外),也不要返回指向内部数据成员的指针或引用供外部代码修改。通过提供抽象,我们将获得插入不变式检查的能力。
  
  第12条:懂得何时和如何进行并发性编程
  
  这个问题主要是考虑多线程和多进程的编程,我期待着并行程序设计进入C++的领域。要编写正确、安全的多线程代码并不简单,非凡是考虑到可移植性时,更是如此。
  
  不过,本条目的题目太大了,很难在一个条目中描述完整,只能概述几个要点:
  
  ·参考目标平台文档,了解该平台的同步化原语。
  
  ·最好将平台原语用自己设计的抽象包装起来
  
  ·确保正在使用的类型在多线程程序中使用是安全的
  
  第13条:确保资源为对象所拥有。使用显式的RAII和智能指针
  
  似乎是在《Imperfact C++》中说过:仅仅因为有RAII就值得使用C++。C++/CLI也强调引入确定性析构,确定性析构正式RAII得以实现的基础之一。通过RAII我们能够得到的远远超出一般程序员的想象,在讨论异常安全代码时,将进一步见识RAII的威力。
  
  在实现RAII时,需要小心复制构造和赋值,编译器的版本可能并不正确。另外,需要确保资源为对象所有,不要在一行分配一个以上的资源。下面的代码是不安全的:
  
  Fun(shared_ptrWidget(new Widget), shared_ptrWidget(new Widget));
  
  取而代之的正确方法是:
  
  shared_ptrWidget sp1(new Widget), sp2(new Widget);
  Fun(sp1, sp2);
  

来源:http://www.tulaoshi.com/n/20160219/1610745.html

延伸阅读
    富有活力的语言需要不断改变和成长,C++也不例外。在本文中,Bjarne Stroustrup提出了自己对C++的设计和演化的看法。 !-- frame contents -- !-- /frame contents -- 为了让编译器、工具和类库实现者跟上节奏,让用户吸收标准C++所支持的编程技术,在早有预计的、沉寂了几年之后,委员会再次考虑...
一、绪论 当微软推出VS.NET7实现了可扩展的托管C++后,C++程序员们反映不一。尽管大部分的程序员对于能够继续使用C++感到很欣慰,但几乎所有的人对于托管C++提供的晦涩语法感到很痛苦。微软明显从反馈中感觉到托管C++不是那么成功。 2003年10月6日,ECMA(欧洲计算机制造商协会)宣布成立专家组,负责结合ISO标准C++与通用语言,开发一个可...
C++中,成员指针是最为复杂的语法结构。但在事件驱动和多线程应用中被广泛用于调用回叫函数。在多线程应用中,每个线程都通过指向成员函数的指针来调用该函数。在这样的应用中,如果不用成员指针,编程是非常困难的。 刚遇到这种语法时也许会让你止步不前。但你会发现,使用恰当的类型定义之后,复杂的语法是可以简化的。本文引导你了解成...
本试题仅用于考查C++/C程序员的基本编程技能。内容限于C++/C常用语法,不涉及数据结构、算法以及深奥的语法。考试成绩能反映出考生的编程质量以及对C++/C的理解程度,但不能反映考生的智力和软件开发能力。 笔试时间90分钟。请考生认真答题,切勿轻视。 一、请填写BOOL , float, 指针变量 与零值比较的 if 语句。(10分) ...
下面的是学C++时要注重的。 1.把C++当成一门新的语言学习(和C没啥关系!真的。); 2.看《Thinking In C++》,不要看《C++变成死相》; 3.看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因为他们很难而我们自己是初学者所以就不看; 4.不要被VC、BCB、BC、MC、TC等词汇所迷惑——他...

经验教程

993

收藏

12
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部