注释

一般的,尽量通过清晰的架构逻辑,好的符号命名来提高代码可读性;需要的时候,才辅以注释说明。注释是为了帮助阅读者快速读懂代码,所以要从读者的角度出发,按需注释

注释内容要简洁、明了、无二义性,信息全面且不冗余。

注释跟代码一样重要。写注释时要换位思考,用注释去表达此时读者真正需要的信息。在代码的功能、意图层次上进行注释,即注释解释代码难以表达的意图,不要重复代码信息。修改代码时,也要保证其相关注释的一致性。只改代码,不改注释是一种不文明行为,破坏了代码与注释的一致性,让阅读者迷惑、费解,甚至误解。

注释风格

在 C++ 代码中,使用/ ///都是可以的。按注释的目的和位置,注释可分为不同的类型,如文件头注释、函数头注释、代码注释等等;同一类型的注释应该保持统一的风格。

注意:本文示例代码中,大量使用 '//' 后置注释只是为了更精确的描述问题,并不代表这种注释风格更好。

文件头注释

规则4.2.1 文件头注释必须包含版权许可

  1. /*
  2. * Copyright (c) [2019] [name of copyright holder]
  3. * [Software Name] is licensed under the Mulan PSL v1.
  4. * You can use this software according to the terms and conditions of the Mulan PSL v1.
  5. * You may obtain a copy of Mulan PSL v1 at:
  6. * http://license.coscl.org.cn/MulanPSL
  7. * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
  8. * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
  9. * PURPOSE.
  10. * See the Mulan PSL v1 for more details.
  11. */

函数头注释

规则4.3.1 禁止空有格式的函数头注释

并不是所有的函数都需要函数头注释;函数签名无法表达的信息,加函数头注释辅助说明;

函数头注释统一放在函数声明或定义上方,使用如下风格之一:使用//写函数头

  1. // 单行函数头
  2. int Func1(void);
  3. // 多行函数头
  4. // 第二行
  5. int Func2(void);

使用/ /写函数头

  1. /* 单行函数头 */
  2. int Func1(void);
  3. /*
  4. * 另一种单行函数头
  5. */
  6. int Func2(void);
  7. /*
  8. * 多行函数头
  9. * 第二行
  10. */
  11. int Func3(void);

函数尽量通过函数名自注释,按需写函数头注释。不要写无用、信息冗余的函数头;不要写空有格式的函数头。

函数头注释内容可选,但不限于:功能说明、返回值,性能约束、用法、内存约定、算法实现、可重入的要求等等。模块对外头文件中的函数接口声明,其函数头注释,应当将重要、有用的信息表达清楚。

例:

  1. /*
  2. * 返回实际写入的字节数,-1表示写入失败
  3. * 注意,内存 buf 由调用者负责释放
  4. */
  5. int WriteString(const char *buf, int len);

坏的例子:

  1. /*
  2. * 函数名:WriteString
  3. * 功能:写入字符串
  4. * 参数:
  5. * 返回值:
  6. */
  7. int WriteString(const char *buf, int len);

上面例子中的问题:

  • 参数、返回值,空有格式没内容
  • 函数名信息冗余
  • 关键的 buf 由谁释放没有说清楚

代码注释

规则4.4.1 代码注释放于对应代码的上方或右边

规则4.4.2 注释符与注释内容间要有1空格;右置注释与前面代码至少1空格

代码上方的注释,应该保持对应代码一样的缩进。选择并统一使用如下风格之一:使用//

  1. // 这是单行注释
  2. DoSomething();
  3. // 这是多行注释
  4. // 第二行
  5. DoSomething();

使用/' '/

  1. /* 这是单行注释 */
  2. DoSomething();
  3. /*
  4. * 另一种方式的多行注释
  5. * 第二行
  6. */
  7. DoSomething();

代码右边的注释,与代码之间,至少留1空格,建议不超过4空格。通常使用扩展后的 TAB 键即可实现 1-4 空格的缩进。

选择并统一使用如下风格之一:

  1. int foo = 100; // 放右边的注释
  2. int bar = 200; /* 放右边的注释 */

右置格式在适当的时候,上下对齐会更美观。对齐后的注释,离左边代码最近的那一行,保证1-4空格的间隔。例:

  1. const int kConst = 100; /* 相关的同类注释,可以考虑上下对齐 */
  2. const int kAnotherConst = 200; /* 上下对齐时,与左侧代码保持间隔*/

当右置的注释超过行宽时,请考虑将注释置于代码上方。

规则4.4.3 不用的代码段直接删除,不要注释掉

被注释掉的代码,无法被正常维护;当企图恢复使用这段代码时,极有可能引入易被忽略的缺陷。正确的做法是,不需要的代码直接删除掉。若再需要时,考虑移植或重写这段代码。

这里说的注释掉代码,包括用 / / 和 //,还包括 #if 0, #ifdef NEVER_DEFINED 等等。

建议4.4.1 正式交付给客户的代码不能包含 TODO/TBD/FIXME 注释

TODO/TBD 注释一般用来描述已知待改进、待补充的修改点FIXME 注释一般用来描述已知缺陷它们都应该有统一风格,方便文本搜索统一处理。如:

  1. // TODO(<author-name>): 补充XX处理
  2. // FIXME: XX缺陷