我在读c++老师的课堂笔记,他是这样写的:
使用缩进// OK
永远不要依赖运算符优先级-总是使用括号// OK
总是使用{}块-即使是单行//不可以,为什么??
Const对象在比较的左边// OK
对>= 0的变量使用unsigned,这是个不错的技巧
删除后将指针设置为NULL -双重删除保护//不错
第三种方法我不清楚:放一行进去能得到什么
A{…} ?
例如,下面这段奇怪的代码:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}
将其替换为:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
使用第一个版本的好处是什么?
我正在处理的代码库被那些病态地厌恶大括号的人分散在代码中,对于后来的人来说,它确实可以对可维护性产生影响。
我遇到的最常见的问题是:
if (really incredibly stupidly massively long statement that exceeds the width of the editor) do_foo;
this_looks_like_a_then-statement_but_isn't;
所以当我出现并希望添加一个then语句时,如果我不小心,我很容易以这样的方式结束:
if (really incredibly stupidly massively long statement that exceeds the width of the editor) do_foo;
{
this_looks_like_a_then-statement_but_isn't;
i_want_this_to_be_a_then-statement_but_it's_not;
}
考虑到添加大括号需要1秒左右的时间,并且可以为您节省至少几分钟的调试时间,为什么不选择减少歧义性呢?在我看来这是虚假的节约。
有许多可能的方法来编写控制语句;它们的某些组合可能共存而不损害易读性,但其他组合将引起麻烦。的风格
if (condition)
statement;
可以与其他一些编写控制语句的方法很好地共存,但与其他方法就不那么好了。如果多行受控语句被写成:
if (condition)
{
statement;
statement;
}
那么,从视觉上看,哪些if语句控制单行,哪些语句控制多行就很明显了。然而,多行If语句被写成:
if (condition) {
statement;
statement;
}
那么,如果构造不添加必要的大括号,那么试图扩展单个语句的可能性就会高得多。
如果代码库大量使用这种形式,那么下一行的单个语句if语句也可能有问题
if (condition) statement;
我个人的偏好是将语句放在自己的行上通常可以提高易读性,除非有许多if语句具有类似的控制块,例如。
if (x1 > xmax) x1 = xmax;
if (x1 < xmin) x1 = xmin;
if (x2 > xmax) x2 = xmax;
if (x2 < xmin) x2 = xmin;
etc.
在这种情况下,我通常会在这些if语句的前面和后面加上一个空行,以便在视觉上将它们与其他代码分开。在相同的缩进处使用一系列以if开头的语句将提供一个清晰的视觉指示,表明有不寻常的地方。
我对这位讲师的能力表示怀疑。考虑到他
点:
OK
Would anyone really write (or want to read) (b*b) - ((4*a)*c)?
Some precedences are obvious (or should be), and the extra parentheses
just add to confusion. (On the other hand, you _should_ use the
parentheses in less obvious cases, even if you know that they're not
needed.)
Sort of. There are two wide spread conventions for formatting
conditionals and loops:
if ( cond ) {
code;
}
and:
if ( cond )
{
code;
}
In the first, I'd agree with him. The opening { is not that visible,
so it's best to assume it's always there. In the second, however, I
(and most of the people I've worked with) have no problem with omitting
the braces for a single statement. (Provided, of course, that the
indentation is systematic and that you use this style consistently.
(And a lot of very good programmers, writing very readable code, omit
the braces even when formatting the first way.)
NO. Things like if ( NULL == ptr ) are ugly enough to hinder
readability. Write the comparisons intuitively. (Which in many cases
results in the constant on the right.) His 4 is bad advice; anything
which makes the code unnatural makes it less readable.
NO. Anything but int is reserved for special cases. To
experienced C and C++ programmers, the use of unsigned signals bit
operators. C++ doesn't have a real cardinal type (or any other
effective subrange type); unsigned doesn't work for numeric values,
because of the promotion rules. Numerical values on which no
arithmetic operations would make sense, like serial numbers, could
presumably be unsigned. I'd argue against it, however, because it
sends the wrong message: bitwise operations don't make sense either.
The basic rule is that integral types are int, _unless_ there is a
significant reason for using another type.
NO. Doing this systematically is misleading, and doesn't actually
protect against anything. In strict OO code, delete this; is often
the most frequent case (and you can't set this to NULL), and
otherwise, most delete are in destructors, so you can't access the
pointer later anyway. And setting it to NULL doesn't do anything
about any other pointers floating around. Setting the pointer
systematically to NULL gives a false sense of security, and doesn't
really buy you anything.
查看任何典型参考文献中的代码。Stroustrup违反
除了第一条,你给出的每一条规则。
我建议你换个讲师。一个真正知道什么的人
他说的是。
另一个添加花括号的例子。
有一次我在搜索一个bug,发现了这样的代码:
void SomeSimpleEventHandler()
{
SomeStatementAtTheBeginningNumber1;
if (conditionX) SomeRegularStatement;
SomeStatementAtTheBeginningNumber2;
SomeStatementAtTheBeginningNumber3;
if (!SomeConditionIsMet()) return;
OtherwiseSomeAdditionalStatement1;
OtherwiseSomeAdditionalStatement2;
OtherwiseSomeAdditionalStatement3;
}
如果你逐行阅读这个方法,你会注意到方法中有一个条件,如果不为真就返回。但实际上,它看起来像其他100个简单的事件处理程序,它们基于某些条件设置一些变量。有一天,Fast Coder进来了,在方法的末尾添加了额外的变量设置语句:
{
...
OtherwiseSomeAdditionalStatement3;
SetAnotherVariableUnconditionally;
}
因此,setanothervariable无条件地在SomeConditionIsMet()时执行,但速度快的家伙没有注意到它,因为所有的行几乎都是相似的大小,即使返回条件垂直缩进,它也不那么明显。
如果条件返回的格式如下:
if (!SomeConditionIsMet())
{
return;
}
它是非常明显的,快速编码器一眼就能发现它。
我能想到的最贴切的例子是:
if(someCondition)
if(someOtherCondition)
DoSomething();
else
DoSomethingElse();
Which if will the else be paired with? Indentation implies that the outer if gets the else, but that's not actually how the compiler will see it; the inner if will get the else, and the outer if doesn't. You would have to know that (or see it behave that way in debugging mode) to figure out by inspection why this code might be failing your expectations. It gets more confusing if you know Python; in that case you know that indentation defines code blocks, so you would expect it to evaluate according to the indentation. C#, however, doesn't give a flying flip about whitespace.
话虽如此,从表面上看,我并不特别同意这个“总是使用括号”的规则。它使代码的垂直噪声非常大,降低了快速读取代码的能力。如果语句是:
if(someCondition)
DoSomething();
... then it should be written just like this. The statement "always use brackets" sounds like "always surround mathematical operations with parentheses". That would turn the very simple statement a * b + c / d into ((a * b) + (c / d)), introducing the possibility of missing a close-paren (the bane of many a coder), and for what? The order of operations is well-known and well-enforced, so the parentheses are redundant. You'd only use parentheses to enforce a different order of operations than would normally be applied: a * (b+c) / d for instance. Block braces are similar; use them to define what you want to do in cases where it differs from the default, and is not "obvious" (subjective, but usually pretty common-sense).