C++ style guide (C++ 编程特性)

C++的style guide 来自cs106b

Stanford class style guide C++
Google style guide C++
Google 所有语言 style guide

C++ 特性

C++语言功能

  • 与C习惯用法相比,更喜欢C ++习惯用法:由于C ++基于C,因此通常有一种“ C ++方式”来完成给定的任务,也有一种“ C方式”。例如,打印输出的“ C ++方式”是通过输出流cout,而“ C方式”是使用printf。C ++字符串使用string类,旧代码使用C-style 。首选现代C ++方式。
    C和C++用法

  • for vs while:for当已知重复次数(确定)时使用循环;while当重复次数未知(不确定)时使用循环。
    for-while

  • 在循环中中断和继续:在任何可能的情况下,循环应该以普通的方式构建,具有清晰的循环开始、停止、推进和不中断的循环控制。也就是说,有一些有限的break使用是可以的,或者需要在迭代中退出循环。continue很少使用,通常会使读者感到困惑,最好避免使用。

  • 在开关情况下使用跌落(fallthrough):开关情况几乎总是以中断或返回结束,以防止继续进入后续情况。在非常罕见的情况下,你打算失败,添加一个评论,使其清楚。意外的跌落(fallthrough)是许多困难的bug的根源。
    fallthrough

  • return statements 虽然允许一个函数有多个return语句,但在大多数情况下,最好是在函数的末尾遍历单个return语句。对于递归基本情况或在函数开始处处理错误来说,早期返回可能是一个清晰的选项。return也可以作为循环退出。然而,在函数中散布其他返回值并不是一个好主意——经验表明,它们会造成不成比例的错误数量。很容易忽略提前返回的情况,错误地认为函数一直运行到最后。

  • Always include {} on control statements:if/else、for、while等语句的正文应该总是用{}包装,并有适当的换行,即使正文只有一行。使用大括号可以防止左图所示的事故。
    控制语句

  • 布尔型:布尔表达式容易产生冗余或笨拙的结构。选择简洁直接的替代方案。一个布尔值是true或false,你不需要进一步比较true/false或将一个布尔表达式转换为true/false。
    bool

  • 使用||,还有!over and、or和not:由于各种主要与国际兼容性有关的原因,c++有两种表示逻辑连接词and、or和not的方式。传统上,运算符&&,||,和!分别用于AND、OR和NOT,且操作符是表示复合布尔值的首选方式。可以用and、or和not来代替,但是这样做是非常不寻常的,而且对于习惯于传统操作符的c++程序员来说有点不和谐。
    逻辑连接词

  • 使用error来报告致命的情况:来自Stanford库的error函数可以用来报告带有您的自定义消息的致命错误。使用error比抛出原始c++异常更可取,因为它与调试器和我们的SimpleTest框架配合得很好。
    error

高效

在CS106B中,我们重视数据结构和算法的有效选择,特别是在有显著收益的情况下,但不热衷于微优化,因为这些微优化会使代码变得混乱,而收益很少。

  • 更好的BigO类:在实现算法的选项中,通常会选择具有更好大O的算法,即O(NlogN)算法优于二次O(N²)、常数O(1)或对数O(logN)算法优于线性O(N)。
  • 根据情况选择最佳性能的ADT:例如,如果您需要对collection执行许多查找操作,那么Set会比Vector更可取,因为它具有高效的contains操作。所有的堆栈/队列操作都是O(1)使堆栈成为一个理想的选择,如果您只在顶部添加/删除,或队列完美,如果您从头部删除和添加在尾部。当您不需要按排序顺序访问元素时,选择HashSet/HashMap而不是Set/Map有一个小小的优势。
  • 保存昂贵的调用结果并重用:如果您正在调用一个昂贵的函数并多次使用其结果,则将结果保存在一个变量中,而不必多次调用函数。这种优化在循环体中特别有价值。
    在这里插入图片描述
  • 避免复制大型对象:当传递对象作为参数或从函数返回对象时,必须复制整个对象。复制大型对象(如收集ADTs)的成本可能很高。通过引用传递对象避免这种开销。然后,客户机和函数共享对单个实例的访问。
    复制大型对象

统一通用代码,避免冗余

当你起草代码时,你可能会发现,当你需要重复执行相同或类似的任务时,你会重复或复制/粘贴代码块。将重复的代码统一到一段可以简化你的设计,并且意味着只需要编写、测试、调试、更新和注释一段代码。

  • 分解为helper函数:提取通用代码并移动到helper函数。
    helper
  • 提取公共代码:从连接的if-else或开关的不同情况提取公共代码。
    在这里插入图片描述

Function design

一个设计良好的函数具有如下属性:

  • 执行一项独立的、连贯的任务。

  • 不做太多的工作。

  • 不会不必要地与其他函数纠缠在一起。

  • 使用参数来实现灵活性/重用(而不是单任务工具)。

  • 明确信息in(参数)和out(返回值)之间的关系

  • 函数结构:一个过长的函数(比如超过20-30行)非常笨拙,应该分解成更小的子函数。如果你试图描述函数的用途,发现自己经常使用“和”这个词,这可能意味着函数做了太多的事情,应该被细分。

  • 值与引用形参:当需要修改传入的形参的值或从函数发送信息时,使用引用形参。不要在不必要或无益的情况下使用引用参数。注意,a、b和c不是下面函数中的引用形参,因为它们不需要是。
    引用

  • 使用返回值而不是引用’out’形参来实现单值返回:如果一个单值需要从函数返回,使用返回值比使用引用’out’形参更简洁。
    在这里插入图片描述

  • 避免“链接”调用: 即许多函数在一个链中彼此调用而不返回main。下面是有(左)和没有(右)链接的调用流示意图:

  • 在这里插入图片描述

注解

一定要注意你的最终评论是否符合你的最终结果。

  • 文件/类头文件:每个文件都应该有一个概述注释来描述该文件的用途。对于作业,这个标题应该包括你的名字,以及这个文件与作业关系的简要描述。

  • 引用源代码:如果你的代码受到外部资源(网页、书籍、其他人等)的重大影响,那么源代码必须被引用。在文件顶部的注释中添加引用。明确说明接受了什么帮助,以及它如何/在哪里影响了你的代码。

  • 函数头:每个函数都应该有一个头注释来描述函数的高级行为,以及以下信息:

  • 参数/返回:给出进入函数的每个参数的类型和用途,以及返回值的类型和用途。

  • 前提/假设:客户应该知道的约束/期望。(“此函数期望文件能够打开以进行读取”)。

  • error:列出函数处理的任何特殊情况或错误条件(例如:"…如果除数为0则抛出错误",或者"…如果单词不存在则返回常量NOT_FOUND ")。

  • 内联注释:内联注释应该在代码复杂或异常到足以保证这样解释的地方少用。一个好的经验法则是:解释代码实现了什么,而不是重复代码说了什么。如果代码完成的任务很明显,那么就不用麻烦了。
    在这里插入图片描述

  • TODO 在提交程序之前,删除程序中的任何// TODO:注释。

  • 注释掉的代码:提交带有大量“注释掉”代码的程序被认为是糟糕的风格。在处理程序时注释掉代码是可以的,但如果程序已经完成,而不需要这样的代码,那么就删除它。

  • Doc注释:你可以使用“Doc”样式(/**…/)如果你喜欢,可以使用注释样式,但这个类不需要注释样式。注释使用//或/…*/很好。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值