【问题标题】:Is it a bad practice to use C-style comments in C++ code? [closed]在 C++ 代码中使用 C 风格的注释是一种不好的做法吗? [关闭]
【发布时间】:2014-02-14 12:51:04
【问题描述】:

在阅读this 维基百科关于 的文章时,我看到了这样的声明:

许多程序员避免使用 C 风格的 cmets,而是使用 C++ 样式单行 cmets。

这是正确的吗?如果是这样,那是为什么?这只是一种习惯还是背后有一些技术和理性的原因?


来自上述文章的示例:

/**
 * <A short one line description>
 *
 * <Longer description>
 * <May span multiple lines or paragraphs as needed>
 *
 * @param  Description of method's or function's input parameter
 * @param  ...
 * @return Description of the return value
 */

对比

/// <A short one line description>
///
/// <Longer description>
/// <May span multiple lines or paragraphs as needed>
///
/// @param  Description of method's or function's input parameter
/// @param  ...
/// @return Description of the return value

【问题讨论】:

  • 对于多行,我将使用/* */,但对于单行、较小的评论,我更喜欢//
  • @GrijeshChauhan,我也是这样做的。但问题是,为什么要对多行 cmets 使用 //
  • 一个可能的原因是您可以快速注释掉包含// cmets 但不包含/* */ cmets 的代码块。
  • #if 0 ... #endif 适合注释掉代码。
  • 我更喜欢 C++ 风格的 cmets,因为你总能知道——即使脱离上下文——一行是否已被注释。我之前在grepping的时候被C风格的cmets烧了。

标签: doxygen c++ coding-style comments


【解决方案1】:

C 风格的 cmets /* */ 不能递归嵌套。像这样'//////' 这样将多个单行 cmets 相互堆叠起来不是问题。这样您就可以逐步注释掉代码的一部分。 例如,Visual Studio 通过以这种方式增加/减少评论级别数量的功能来支持这一点。

支持 '/* */' 样式 cmets 的一个原因是在滚动代码(例如方法文档)时使特殊类型的 cmets 突出。这也为代码创建了一个很好的视觉结构。

'/* */' cmets 的另一个用例是内联 cmets,它具有两边的代码,例如 void myfunc(double size /* = 0 */) { ... } 以使默认值在 cpp 文件中可见.

结合这两种好处的一种可能方法是:

  • 在方法内部使用“//”(您想在其中重复注释/注释掉)和
  • 仅对特殊类型的 cmets 使用“/* */”,例如 cpp 中的 doxygen 文档。

【讨论】:

  • 这是 IDE 或文本编辑器在自动插入 cmets 时使用单行 cmets 的一个很好的理由。但这不是避免自己使用它们的好理由,除非您的工具太差以至于您必须自己注释掉,在这种情况下,您需要解决更严重的生产力问题:-)
  • 注释掉代码不是很好的做法(使用版本控制),两边都有代码的内联 cmets 很奇怪。
【解决方案2】:

现在既没有 C 风格的 cmets 也没有 C++ 风格的 cmets,因为 C 和 C++ 都支持这两种 cmets, 因此,在一行的末尾最好使用 // cmets,而当使用 /* ..*/ cmets 时,一长段 cmets 更具可读性。

就我而言,我通常更喜欢使用 /*.. */ cmets 来对我放在函数定义或声明之前的函数进行一般描述。如果我需要在一些 sn-p 代码中的某个语句中添加注释,并且只插入一行 cmets 就足够了,我使用 // 注释。

【讨论】:

    【解决方案3】:

    我认为这真的是一个品味问题。

    有许多约定,只要有多个选项可用,总会有讨论。匈牙利符号与非匈牙利符号、蛇形符号与骆驼形符号等也是如此。

    一般来说,这取决于几个因素:

    1) 什么是可接受的风格。 如果你在大型项目中工作,你通常必须(并且应该)遵守编码风格的一般规则。在同一个项目的不同文件中有不同的注释样式是非常不希望的。

    2) 大多数团队喜欢什么。 应讨论接受的约定以适应开发人员的偏好。应该没有压力 - 只要每个人都同意一切都很好。

    3) 技术要求是什么。 如果你需要某种形式的嵌套,你应该仔细考虑。多行注释不能嵌套。按以下顺序:

    /* -> 1 开始 /* -> 2 开始 */ -> 2 结束 */ -> 1 结束

    '2 start' 不会被识别为注释,'2 end' 将匹配 '1 start' 而 '1 end' 将引发编译器错误。

    4) 应该使用特定注释时。 在创建类的一般描述(例如)时,可能希望使用 /* */ 创建多行、强描述性的注释。在代码的一部分(单个表达式、方法参数描述或附加注释)中插入简短描述时,简单的单行注释 (//) 可能是一个更好的主意。

    另外,值得一提的是,ML cmets被假定为多行。这是什么意思:例如在 Visual Studio 中,在创建 DOC 注释之后:

    /** * */

    在评论中按回车后会自动添加星(*),让您无需额外工作即可创建好看的评论:

    /** * 一些不错的描述 [按此处输入] * //-> 这是由编辑器插入的 */

    如果多行 cmets 使用单行标记 (//),您需要在每一行手动添加它们。

    在一种情况下,您应该使用单行注释:使用 Visual Studio。我的意思是什么? VS 有一个很好的功能来注释/取消注释代码块。这些任务有特殊的快捷键 - Ctrl-K、Ctrl-C 用于注释,Ctrl-K、Ctrl-U 用于取消注释。现在,编辑器将检查应该使用哪种类型的 cmets:

    void f()
    {
      int p = 0;
      int k = 0;
      while(true) {
        ++p;
        ++k;
      }
    }
    

    让我们评论整个函数 [Pressing Ctrl-K-C...]。结果如下:

    //void f()
    //{
    //  int p = 0;
    //  int k = 0;
    //  while(true) {
    //    ++p;
    //    ++k;
    //  }
    //}
    

    让我们在正文中进行注释并使其为空[按 Ctrl-K-C...]。结果如下:

    void f()
    {
      int p = 0;
      int k = 0;
      while(true); /*{ -> comment was invoked inside the line, multiline is required.
        ++p;
        ++k;
      }*/
    }
    

    在预测时使用单行注释非常重要,因为某些部分代码可能会暂时从源代码中排除。让我们想一想如果我们的 while 正文包含注释会发生什么:

    1) 第一种情况,SL 注释:

    //void f()
    //{
    //  int p = 0;
    //  int k = 0;
    //  while(true) {
    //    ++p; //some comment -> ok, '//' can be nested
    //    ++k;
    //  }
    //}
    

    2) 第一种情况,ML 注释:

    //void f()
    //{
    //  int p = 0;
    //  int k = 0;
    //  while(true) {
    //    ++p; /*some comment*/ -> ok, '/**/' can be nested inside //
    //    ++k;
    //  }
    //}
    

    3) 第二种情况,SL 注释:

    void f()
    {
      int p = 0;
      int k = 0;
      while(true); /*{ -> comment was invoked inside the line, multiline  is required.
        ++p; //some comment -> ok, '//' can be nested inside multiline 
        ++k;
      }*/
    }
    

    4) 第二种情况,ML 注释:

    void f()
    {
      int p = 0;
      int k = 0;
      while(true); /*{ -> comment was invoked inside the line, multiline  is required.
        ++p; /*some comment*/
        ++k;
      }*/ -> oh..
    }
    

    由于 SO 使用相同的规则解析 cmets,您应该看到上一个示例中的最后一个标记没有变灰。从我的角度来看,这很重要,因为我经常使用阻止(取消)评论。

    【讨论】:

      【解决方案4】:

      这完全是关于什么是可接受的风格的问题 - 在任何一种语言中使用一种风格而不是另一种风格没有技术原因(除非你有一个非常旧的编译器)。

      一些社区会期待一种风格的 cmets - 例如,Linux 内核(一个 C 社区)会期待 C 风格的 cmets,但内核源代码的快速 grep 显示一些 C++ 风格的 cmets 已经实现了。

      因此,如果您正在为一个项目做出贡献,那么您应该遵循那里已经使用的样式。如果您是单独工作或类似工作,您可以使用您喜欢的 - 尽管最好不要混合样式。

      【讨论】:

        猜你喜欢
        • 2011-04-05
        • 2011-12-22
        • 2019-05-01
        • 1970-01-01
        • 2015-05-31
        • 1970-01-01
        • 1970-01-01
        • 2012-02-29
        • 1970-01-01
        相关资源
        最近更新 更多