我在读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 (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违反
除了第一条,你给出的每一条规则。
我建议你换个讲师。一个真正知道什么的人
他说的是。
让我们尝试在增加j时也修改i:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
i++;
噢,不!来自Python,这看起来不错,但实际上不是,因为它相当于:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
i++;
当然,这是一个愚蠢的错误,但即使是有经验的程序员也会犯这个错误。
在ta.speot中指出了另一个很好的理由。的回答。
我能想到的第三个是嵌套的if:
if (cond1)
if (cond2)
doSomething();
现在,假设您现在想在未满足cond1时执行somethingelse()(新特性)。所以:
if (cond1)
if (cond2)
doSomething();
else
doSomethingElse();
这显然是错误的,因为else与内部的if相关联。
编辑:既然这引起了一些关注,我将澄清我的观点。我想回答的问题是
使用第一个版本的好处是什么?
我已经描述过了。有一些好处。但是,在我看来,“总是”的规则并不总是适用。所以我并不完全支持
总是使用{}块-即使是单行//不可以,为什么??
我并不是说总是使用{}块。如果这是一个足够简单的条件和行为,那就不要。如果你怀疑有人可能稍后会来修改你的代码来增加功能,那就这么做。
我正在处理的代码库被那些病态地厌恶大括号的人分散在代码中,对于后来的人来说,它确实可以对可维护性产生影响。
我遇到的最常见的问题是:
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秒左右的时间,并且可以为您节省至少几分钟的调试时间,为什么不选择减少歧义性呢?在我看来这是虚假的节约。
为了补充之前回答中非常明智的建议,我在重构一些代码时遇到的一个例子是:我正在修改一个非常大的代码库,从一个API切换到另一个API。第一个API调用设置Company Id,如下:
setCompIds( const std::string& compId, const std::string& compSubId );
而替换需要两次调用:
setCompId( const std::string& compId );
setCompSubId( const std::string& compSubId );
我开始使用正则表达式来改变这种情况,这非常成功。我们还通过样式传递代码,这确实使它更易于阅读。然后,在审查过程中,我发现在某些条件下,它正在改变:
if ( condition )
setCompIds( compId, compSubId );
:
if ( condition )
setCompId( compId );
setCompSubId( compSubId );
这显然不是我们所需要的。我不得不回到一开始,再次将替换处理为完全在一个块内,然后手动修改任何最终看起来愚蠢的东西(至少它不会是不正确的)。
我注意到style现在有了一个选项——add-括号,它允许你在没有括号的地方添加括号,如果你发现自己处于和我一样的位置,我强烈建议你这样做。
另一个添加花括号的例子。
有一次我在搜索一个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;
}
它是非常明显的,快速编码器一眼就能发现它。