C++ 轻量化C++;编码标准

C++ 轻量化C++;编码标准,c++,coding-style,C++,Coding Style,我一直参与开发非常详细的编码标准。我自己的经验是,如果没有适当的流程来维护它,并且没有策略来维护它,那么很难实施 现在,我在一个环境中工作,并领导一个在相当长一段时间内不太可能有流程和后续战略的环境。但我仍然希望维护一些最低级别的体面代码。所以我想我会在这里得到很好的建议,我们可能会一起产生一个合理的最重要的编码标准实践的轻量级子集,供其他人参考 因此,为了强调这一点: 强> C++编码标准中哪些元素是最重要的?< /强> 答覆/表决规则 每个答案1名候选人,最好是有简短的动机 投票否决注重

我一直参与开发非常详细的编码标准。我自己的经验是,如果没有适当的流程来维护它,并且没有策略来维护它,那么很难实施

现在,我在一个环境中工作,并领导一个在相当长一段时间内不太可能有流程和后续战略的环境。但我仍然希望维护一些最低级别的体面代码。所以我想我会在这里得到很好的建议,我们可能会一起产生一个合理的最重要的编码标准实践的轻量级子集,供其他人参考

因此,为了强调这一点:

<>强> C++编码标准中哪些元素是最重要的?< /强>
  • 答覆/表决规则
    • 每个答案1名候选人,最好是有简短的动机

    • 投票否决注重风格和主观格式准则的候选人。这并不是说它们不重要,只是说它们在这方面不太相关

    • 投票否决关注如何评论/记录代码的候选人。这是一个更大的主题,甚至可能值得发表自己的文章

    • 投票支持明显促进更安全代码的候选代码,从而最大限度地降低神秘错误的风险,提高可维护性等

    • 不要向你不确定的候选人投任何方向的票。即使它们听起来合理而聪明,或者相反“肯定没人会用的东西”,你的投票应该基于清楚的理解和经验

如果正在使用(或预计使用)的工具链对异常的实现效率低下,那么最好避免使用它们。我在这样的条件下工作过

更新:是其他人对“嵌入式C++”的解释,它似乎排除了例外。它提出以下几点:

  • 很难估计异常发生与控制传递给相应异常处理程序之间的时间
  • 很难估计异常处理的内存消耗

那页上有更详细的文字,我不想全部复制。另外,它已经有10年的历史了,所以它可能不再有用了,这就是为什么我在文章中提到了关于工具链的部分。也许还应该读“如果内存不是主要问题”,和/或“如果不需要可预测的实时响应”,等等。

为保持一致性,在通用命名方案中使用方法和变量名;在阅读源代码时,我不会为其他任何事情而烦恼。

如果缩进的步骤不止一步,则需要大括号:

if (bla) {
  for (int i = 0; i < n; ++i)
    foo();
}
if(bla){
对于(int i=0;i

这有助于使缩进与编译器对代码的看法保持一致。

将函数保持在合理的大小。就个人而言,我喜欢将函数保持在25行以下。当您可以将函数作为一个单元引入时,可读性得到了增强,而不必上下扫描以了解它是如何工作的。如果你必须滚动阅读,这会让事情变得更糟。

只不过是简单地使用了?:接线员,即

float x = (y > 3) ? 1.0f : -1.0f;
可以,但这不是:

float x = foo(2 * ((y > 3) ? a : b) - 1);

确保编译器的警告级别设置得足够高(最好是/Wall),以便它能够捕捉到愚蠢的错误,例如:

if (p = 0)
当你真正的意思是

if (p == 0)
这样你就不需要采取更愚蠢的手段,比如:

if (0 == p)
这会降低代码的可读性。

所有假设,包括临时假设,如未实现的行为。断言函数入口和出口条件(如果非平凡)。断言所有非平凡的中间状态。如果断言没有首先失败,您的程序永远不会崩溃。您可以自定义断言机制以忽略将来发生的事件

对预期发生的情况使用错误处理代码;对不应发生的情况使用断言。错误处理通常检查错误的输入数据;断言检查代码中的错误

如果错误处理代码用于解决异常情况,则错误处理将使程序能够优雅地响应错误。如果针对异常情况触发断言,则纠正措施不仅仅是优雅地处理错误,而是更改程序的源代码、重新编译并发布软件的新版本。将断言视为可执行文档是一种很好的方法,您不能依赖它们来让代码工作,但它们可以比程序语言注释更积极地记录假设[1]

  • 麦康奈尔,史蒂夫。代码完成,第二版。微软出版社©2004。第8章-防御性编程

  • 任何控制语句的花括号。(多亏了自己的经验,并通过阅读代码完整v2得到了加强):

    //糟糕的例子-作者写的东西
    if(i<0)
    printf(“%d\n”,i);
    ++i、 //这个错误很容易被忽略!
    //好例子——作者的意思是什么
    if(i<0){
    printf(“%d\n”,i);
    ++一,;
    }
    
    首选


    STL的自动(并在boost&C++0x中共享)指针可能会有所帮助。

    尽可能使用引用而不是指针。这可以防止持续的防御性空检查。

    使用lint工具-即PC lint。这将抓住许多“结构性”编码准则问题。这意味着读到的是实际的bug,而不是样式/可读性问题。(不是说可读性不重要,而是比实际错误更重要)

    例如,不需要此样式:

    if (5 == variable)
    

    作为防止“意外分配”错误的一种方法,让lint找到它。

    无论有什么指导原则,都要让它非常容易识别适用性:你的选择越少,你选择的时间就越少
    if (5 == variable)
    
    struct A {
        const int i;
    };
    
    bool operator<(const A& lhs, const A& rhs) {
        return lhs.i < rhs.i;
    }
    
    int main() {
        std::vector<A> as;
        as.emplace_back(A{1});
        std::sort(begin(as), end(as));
    }
    
    ... note: copy assignment operator of 'A' is implicitly deleted because
    field 'i' is of const-qualified type 'const int'
    ...
    in instantiation of function template specialization 'std::sort<...>'
    requested here
    
        std::sort(begin(as), end(as));
    
    
    struct MyStruct // BAD
    {
       int i ; bool j ; char * k ;
    }
    
    struct MyStruct // GOOD
    {
       MyStruct() : i(0), j(true), k(NULL) : {}
    
       int i ; bool j ; char * k ;
    }
    
    MyStruct oMyStruct = { 25, true, "Hello" } ; // BAD
    MyStruct oMyStruct(25, true, "Hello") ;      // GOOD
    
    void doSomething()
    {
       MyStruct s = { 25, true, "Hello" } ;
      // Etc.
    }
    
    void doSomethingElse()
    {
       MyStruct s = { 25, true, "Hello" } ;
      // Etc.
    }
    
    // Etc.
    
    // char * d, * s ;
    strcpy(d, s) ; // BAD
    
    // std::string d, s ;
    d = s ;        // GOOD
    
    int * i = (int *) malloc(25) ; // Now, I BELIEVE I have an array of 25 ints!
    int * j = new int[25] ;        // Now, I KNOW I have an array of 25 ints!
    
    class foo { //... private: foo( const foo& ); const foo& operator=( const foo& ); }; class foo : private boost::noncopyable { ... };
    SolveLinearSystem(left_hand_side, right_hand_side, &params);