10

您遵循哪些准则来提高代码的总体质量?许多人都有关于如何编写 C++ 代码的规则(据说)这使得出错变得更加困难。我见过有人坚持每条if语句后跟一个大括号({...})。

我对其他人遵循的指导方针及其背后的原因很感兴趣。我也对你认为是垃圾但普遍持有的指导方针感兴趣。谁能推荐几个?

为了让球滚动,我将首先提到一些:

  • 始终在每个if/else语句后使用大括号(如上所述)。这背后的基本原理是,要判断一条语句实际上是一条语句还是扩展为多个语句的预处理器宏并不总是那么容易,因此这段代码会中断:
    // 文件顶部:
    #define 语句 doSomething(); 做点别的

    // 在实现中:
    如果(某些条件)
        做点什么();

但是如果您使用大括号,那么它将按预期工作。

  • 仅将预处理器宏用于条件编译。预处理器宏可能会导致各种麻烦,因为它们不允许 C++ 范围规则。由于头文件中具有通用名称的预处理器宏,我已经多次搁浅。一不小心,就会造成各种各样的破坏!

现在交给你了。

4

21 回答 21

9

我个人最喜欢的几个:

努力编写const 正确的代码。您将使用编译器来帮助清除易于修复但有时令人痛苦的错误。您的代码还将讲述您在编写它时的想法——一旦您离开,这对新手或维护者都很有价值。

退出内存管理业务。学习使用智能指针:std::auto_ptrstd::tr1::shared_ptr(或boost::shared_ptr)和boost::scoped_ptr。了解它们之间的区别以及何时使用它们。

您可能会使用标准模板库。阅读Josuttis 的书。不要只是在读完关于容器的前几章后就停下来,以为你知道 STL。推进好东西:算法和函数对象。

于 2008-09-13T17:28:03.663 回答
9
  1. 删除不必要的代码。

就这些。

于 2008-09-13T18:00:22.727 回答
7
  • 使用并执行通用的编码风格和准则。理由:团队或公司中的每个开发人员都能够阅读代码,而不会因不同的大括号样式或类似情况而分心。
  • 定期对整个源代码库进行全面重建(即每日构建或每次签入后构建)并报告任何错误!理由:源几乎总是处于可用状态,问题在“实施”后不久就会被检测到,而解决问题的成本很低。
于 2008-09-13T16:57:26.793 回答
7

打开编译器中可以出现的所有警告(gcc:-Wall是一个好的开始,但不包括所有内容,因此请查看文档),并使它们出错,因此您必须修复它们(gcc: -Werror)。

于 2008-09-13T19:46:10.227 回答
5

这些答案之一中提到的 Google 风格指南非常可靠。里面有一些毫无意义的东西,但总比坏的好。

Sutter 和 Alexandrescu 就这个主题写了一本不错的书,名为C++ Coding Standards

以下是 lil' ole me 的一些一般提示:

  1. 您的缩进和括号样式都是错误的。其他人的也是如此。因此,请遵循项目的标准。吞下你的骄傲并设置你的编辑器,以便一切都尽可能与代码库的其余部分保持一致。不得不阅读缩进不一致的代码真的很烦人。也就是说,括号和缩进与“改进代码”没有任何关系。更多的是提高你与他人合作的能力。

  2. 好好评论。这是非常主观的,但一般来说,写评论为什么代码会以它的方式工作总是好的,而不是解释它的作用。当然,对于复杂的代码,可能不熟悉算法或代码的程序员也可以了解在做什么。非常欢迎链接到所用算法的描述。

  3. 以尽可能直接的方式表达逻辑。我认为具有讽刺意味的是,像“将常量放在比较左侧”这样的建议在这里出错了。它们非常受欢迎,但对于说英语的人来说,它们经常会破坏程序的逻辑流程以供阅读者使用。如果您不能相信自己(或您的编译器)能够正确编写相等比较,那么请务必使用这样的技巧。但是当你这样做时,你会牺牲清晰度。也属于这一类的还有......“我的逻辑有 3 级缩进吗?它可以更简单吗?” 并将类似的代码滚动到函数中。甚至可能拆分功能。编写优雅地表达底层逻辑的代码需要经验,但值得努力。

那些很一般。对于具体的提示,我不能比 Sutter 和 Alexandrescu 做得更好。

于 2008-09-14T11:09:29.493 回答
4

在 if 语句中,将常量放在左侧,即

if( 12 == var )

不是

if( var == 12 )

因为如果你错过了输入“=”,那么它就变成了作业。在最高版本中,编译器说这是不可能的,在后者中它运行并且 if 始终为真。

每当它们不在同一行时,我都会为 if 使用大括号。

if( a == b ) something();
if( b == d )
{
    bigLongStringOfStuffThatWontFitOnASingleLineNeatly();
}

打开和关闭大括号总是有自己的行。但这当然是个人惯例。

于 2008-09-13T17:32:34.853 回答
4

仅在仅需要解释代码在做什么时才发表评论,而阅读代码无法告诉您相同的信息。

不要注释掉不再使用的代码。如果要恢复旧代码,请使用源代码控制系统。注释掉代码只会让事情看起来很混乱,并且会让你真正重要的注释淡入注释代码的背景混乱中。

于 2008-09-13T18:19:43.630 回答
3
  1. 使用一致的格式。
  2. 在处理遗留代码时,请使用现有的格式样式,尤其是。大括号样式。
  3. 获取 Scott Meyer 的《Effective C++》一书的副本
  4. 获取 Steve MConnell 的书 Code Complete 的副本。
于 2008-09-13T18:13:00.263 回答
3

Google 内部还使用了一个不错的C++ 样式指南,其中包括这里提到的大部分规则。

于 2008-09-14T07:35:47.073 回答
2

开始写很多评论——但以此为契机重构代码,使其具有自我解释性。

IE:

for(int i=0; i<=arr.length; i++) {
  arr[i].conf() //confirm that every username doesn't contain invalid characters
}

应该更像

for(int i=0; i<=activeusers.length; i++) {
  activeusers[i].UsernameStripInvalidChars()
}
于 2008-09-15T17:35:45.670 回答
1

类似地,您可能会在这里找到一些有用的建议:如何使错误的代码看起来不正确?您使用什么模式来避免语义错误?

于 2008-09-13T17:44:11.563 回答
1
  • 使用制表符进行缩进,但将数据与空格对齐这意味着人们可以通过更改制表符大小来决定缩进多少,但也可以保持对齐(例如,在将值分配给结构)

  • 尽可能使用常量或内联函数而不是宏

  • 永远不要在头文件中使用“使用”,因为包含该头文件的所有内容也会受到影响,即使包含您的头文件的人不希望在其全局命名空间中使用所有 std(例如)。

  • 如果某些内容超过大约 80 列,请将其分成多行,例如

    if(SomeVeryLongVaribleName != LongFunction(AnotherVarible, AString) &&
       BigVaribleIsValid(SomeVeryLongVaribleName))
    {
        DoSomething();
    }
    
  • 仅重载运算符以使它们执行用户期望的操作,例如重载 2dVector 的 + 和 - 运算符就可以了

  • 始终注释您的代码,即使它只是说明下一个块在做什么(例如“删除此级别不需要的所有纹理”)。有人可能需要稍后使用它,可能在你离开之后,他们不想找到没有注释的 1000 行代码来指示什么在做什么。

于 2008-09-13T17:58:58.330 回答
1
  1. 设置编码约定并让所有参与的人都遵守约定(您不希望阅读需要您弄清楚下一个语句/表达式在哪里的代码,因为它没有正确缩进)
  2. 不断地重构你的代码(获取一份 Martin Fowler 的 Refactoring 的副本,书中详细介绍了优缺点)
  3. 编写松散耦合的代码(通过编写不言自明的代码来避免写注释,松散耦合的代码往往更易于管理/适应更改)
  4. 如果可能的话,对你的代码进行单元测试(或者如果你足够有男子气概,那就是 TDD。)
  5. 尽早发布,经常发布
  6. 避免过早优化(分析有助于优化)
于 2008-09-13T19:03:17.193 回答
1

在可能的情况下,使用前增量而不是后增量。

于 2008-09-15T17:25:57.690 回答
1

我在我的 C++ 项目中使用 PC-Lint,尤其喜欢它引用现有出版物的方式,例如 MISRA 指南或 Scott Meyers 的“Effective C++”和“More Effective C++”。即使您计划为静态分析工具检查的每条规则编写非常详细的理由,最好指出您的用户信任的已建立的出版物。

于 2008-09-15T18:11:48.423 回答
1

这是 C++ 大师给我的最重要的一条建议,它帮助我在一些关键场合找到了代码中的错误:

  • 当方法不应该修改对象时使用 const 方法。
  • 当对象不应该修改对象时,在参数中使用 const 引用和指针。

使用这两条规则,编译器将免费告诉您代码中的逻辑缺陷!

于 2008-09-16T07:39:10.057 回答
1

此外,对于一些好的技术,您可以关注Google 的博客“马桶测试”

于 2008-09-16T08:07:15.497 回答
1

六个月后再看

于 2008-10-08T03:31:19.350 回答
0

确保正确缩进

于 2008-09-13T16:50:23.957 回答
0

嗯 - 我可能应该更具体一点。

我并不是在为自己寻找建议——我正在编写一个静态代码分析工具(当前的商业产品还不足以满足我的需求),我正在寻找插件的想法来突出可能代码中的错误。

有几个人提到了诸如 const 正确性和使用智能指针之类的东西——这是我可以检查的那种想法。检查缩进和注释有点难(无论如何从编程的角度来看)。

于 2008-09-14T07:25:29.797 回答
0

智能指针有一种非常清楚地指示所有权的好方法。如果你是一个类或一个函数:

  • 如果你得到一个原始指针,你就没有任何东西。您可以使用指针,由您的呼叫者提供,他保证指针将比您活得更久。
  • 如果你得到一个weak_ptr,你不拥有指针,最重要的是指针可以随时消失。
  • 如果您获得了shared_ptr,则您与其他人一起拥有该对象,因此您无需担心。压力更小,控制也更少。
  • 如果您获得auto_ptr,则您是该对象的唯一所有者。这是你的,你是国王。您有权销毁该对象,或将其交给其他人(从而失去所有权)。

我发现 auto_ptr 的情况特别强大:在设计中,如果我看到一个 auto_ptr,我会立即知道该对象将从系统的一个部分“游走”到另一个部分。

这至少是我在我的宠物项目中使用的逻辑。我不确定这个主题会有多少变化,但到目前为止,这个规则集对我很有帮助。

于 2008-09-16T07:57:12.137 回答