我在读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++;

使用第一个版本的好处是什么?


当前回答

它更直观,更容易理解。它使意图明确。

它还确保当新用户在添加新代码语句时不知不觉地漏掉{,}时,代码不会中断。

其他回答

在“总是使用牙套”的营地呆了10年之后,我最近开始不怎么使用牙套了。 主要是受到Bob叔叔关于如何编写干净代码的争论的启发,我现在相信不使用大括号编写代码更具有可读性。

if(guardClause)
      throw new SomeException(..)

Bob大叔认为,在if/for语句中编写多行代码是潜在的可读性问题。

e.g.

if(someCondition)
{
   doTechnicalThingX();
   doTechnicalThingY();
   doTechnicalThingZ();
}

应该被重构为

if(someCondition)
    doFunctionalThingA();

对我来说,不把大括号放在那里是有帮助的,因为我得到提醒,我在if块中写了太多代码。

正如其他人所提到的,我相信代码风格是团队决策。

让我们尝试在增加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 (condition)
  do_something();
else
  do_something_else();

must_always_do_this();

如果你用一行注释注释掉do_something_else(),你会得到这样的结果:

if (condition)
  do_something();
else
  //do_something_else();

must_always_do_this();

它会编译,但must_always_do_this()并不总是被调用。

我们在代码库中遇到了这个问题,有人在发布之前很快地禁用了一些功能。幸运的是,我们在代码审查中发现了它。

当你完成它时,最好将指针设置为NULL。

下面是一个例子:

A类行为如下:

分配一块内存 然后一段时间后,它删除这块内存,但不将指针设置为NULL

B类做以下事情

分配内存(在这个实例中,它得到的内存块恰好与类a删除的内存块相同)

在这一点上,类A和类B都有指向同一个内存块的指针,就类A而言,这块内存块不存在,因为它已经用完了。

考虑以下问题:

如果在类a中有一个逻辑错误,导致它写入现在属于类B的内存呢?

在这个特定的实例中,您不会得到一个糟糕的访问异常错误,因为内存地址是合法的,而类A现在有效地破坏了类B数据。

类B可能最终崩溃,如果它遇到意外值,当它崩溃时,很有可能,当问题出现在类a时,您将花费相当长的时间在类B中查找这个bug。

如果您已经将删除的内存指针设置为NULL,那么只要类A中的任何逻辑错误试图写入NULL指针,您就会得到一个异常错误。

如果您担心在指针第二次为NULL时使用双重删除会出现逻辑错误,那么可以为此添加assert。

wrt 6:它更安全,因为删除空指针是一个无操作。因此,如果您碰巧两次经过这条路径,您不会因为释放空闲内存或已分配给其他内存而导致内存损坏。

这是静态文件作用域对象和单例对象的主要问题,它们没有非常明确的生命周期,并且已知它们在被销毁后会被重新创建。

在大多数情况下,您可以通过使用auto_ptrs来避免这种需要