我在读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++;
使用第一个版本的好处是什么?
纵观答案,没有人明确地说明了我习惯的那种实践,讲述你的代码的故事:
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++;
}
将j++放在与if should相同的行上,向其他任何人发出信号:“我只想让这个块永远增加j”。当然,只有在行代码尽可能简单的情况下,这样做才有意义,因为在这里设置断点,正如前面提到的,并不是很有用。
事实上,我刚刚遇到了Twitter Storm API的一部分,它在Java中有这种“类型”代码。以下是执行代码的相关片段,在本幻灯片的第43页:
...
Integer Count = counts.get(word);
if (Count=null) count=0;
count++
...
for循环块中有两个东西,所以我不会内联那个代码。也就是说,从来没有:
int j = 0;
for (int i = 0 ; i < 100 ; ++i) if (i % 2 == 0) j++;
这很糟糕,我甚至不知道它是否有效(如预期的那样);不要这样做。新行和大括号有助于区分独立但相关的代码段,就像散文中的逗号或分号一样。上面的块是一个很长的句子,里面有几个从句和一些其他的语句,从来没有中断或暂停来区分不同的部分。
如果你真的想要向其他人发送一个只有一行的任务,请使用三元操作符或?:form:
for (int i = 0 ; i < 100 ; ++i) (i%2 ? 0 : >0) j++;
但这几乎是代码高尔夫,我认为这不是很好的实践(我不清楚是否应该将j++放在:的一侧)。注意,我以前没有在c++中运行过三元运算符,我不知道这是否有效,但它确实存在。
简而言之:
想象一下您的读者(即维护代码的人)如何解释您的故事(代码)。让他们尽可能清楚地知道。如果您知道新手程序员/学生正在维护这个,甚至可能留下尽可能多的{},这样他们就不会感到困惑。
当你完成它时,最好将指针设置为NULL。
下面是一个例子:
A类行为如下:
分配一块内存
然后一段时间后,它删除这块内存,但不将指针设置为NULL
B类做以下事情
分配内存(在这个实例中,它得到的内存块恰好与类a删除的内存块相同)
在这一点上,类A和类B都有指向同一个内存块的指针,就类A而言,这块内存块不存在,因为它已经用完了。
考虑以下问题:
如果在类a中有一个逻辑错误,导致它写入现在属于类B的内存呢?
在这个特定的实例中,您不会得到一个糟糕的访问异常错误,因为内存地址是合法的,而类A现在有效地破坏了类B数据。
类B可能最终崩溃,如果它遇到意外值,当它崩溃时,很有可能,当问题出现在类a时,您将花费相当长的时间在类B中查找这个bug。
如果您已经将删除的内存指针设置为NULL,那么只要类A中的任何逻辑错误试图写入NULL指针,您就会得到一个异常错误。
如果您担心在指针第二次为NULL时使用双重删除会出现逻辑错误,那么可以为此添加assert。
纵观答案,没有人明确地说明了我习惯的那种实践,讲述你的代码的故事:
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++;
}
将j++放在与if should相同的行上,向其他任何人发出信号:“我只想让这个块永远增加j”。当然,只有在行代码尽可能简单的情况下,这样做才有意义,因为在这里设置断点,正如前面提到的,并不是很有用。
事实上,我刚刚遇到了Twitter Storm API的一部分,它在Java中有这种“类型”代码。以下是执行代码的相关片段,在本幻灯片的第43页:
...
Integer Count = counts.get(word);
if (Count=null) count=0;
count++
...
for循环块中有两个东西,所以我不会内联那个代码。也就是说,从来没有:
int j = 0;
for (int i = 0 ; i < 100 ; ++i) if (i % 2 == 0) j++;
这很糟糕,我甚至不知道它是否有效(如预期的那样);不要这样做。新行和大括号有助于区分独立但相关的代码段,就像散文中的逗号或分号一样。上面的块是一个很长的句子,里面有几个从句和一些其他的语句,从来没有中断或暂停来区分不同的部分。
如果你真的想要向其他人发送一个只有一行的任务,请使用三元操作符或?:form:
for (int i = 0 ; i < 100 ; ++i) (i%2 ? 0 : >0) j++;
但这几乎是代码高尔夫,我认为这不是很好的实践(我不清楚是否应该将j++放在:的一侧)。注意,我以前没有在c++中运行过三元运算符,我不知道这是否有效,但它确实存在。
简而言之:
想象一下您的读者(即维护代码的人)如何解释您的故事(代码)。让他们尽可能清楚地知道。如果您知道新手程序员/学生正在维护这个,甚至可能留下尽可能多的{},这样他们就不会感到困惑。
我正在处理的代码库被那些病态地厌恶大括号的人分散在代码中,对于后来的人来说,它确实可以对可维护性产生影响。
我遇到的最常见的问题是:
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秒左右的时间,并且可以为您节省至少几分钟的调试时间,为什么不选择减少歧义性呢?在我看来这是虚假的节约。