今天给同事复查代码时,我发现了一件奇怪的事情。他把他的新代码用大括号括起来,就像这样:

Constructor::Constructor()
{
   // Existing code

   {
      // New code: do some new fancy stuff here
   }

   // Existing code
}

如果有结果的话,结果会是什么?这样做的原因是什么?这种习惯从何而来?

环境是嵌入式设备。有很多遗留的C代码被包裹在c++的外衣里。有很多C转向c++的开发人员。

在这部分代码中没有临界区。我只在这部分代码中看到过。没有完成主要的内存分配,只是设置了一些标志,并进行了一些操作。

用大括号括起来的代码是这样的:

{
   bool isInit;
   (void)isStillInInitMode(&isInit);
   if (isInit) {
     return isInit;
   }
}

(不要介意代码,只要坚持花括号…,)) 在花括号之后,还有更多的位处理、状态检查和基本信号。

我和他谈过,他的动机是限制变量的范围,命名冲突,以及其他一些我不能真正理解的东西。

从我的角度来看,这似乎很奇怪,我认为花括号不应该出现在我们的代码中。在所有关于为什么可以用花括号包围代码的回答中,我看到了一些很好的例子,但你不应该把代码分成方法吗?

fsdf

当前回答

我认为其他人已经讨论了范围,所以我将提到不必要的括号也可能在开发过程中发挥作用。例如,假设您正在对现有函数进行优化。切换优化或跟踪错误到特定的语句序列对程序员来说很简单——参见大括号前的注释:

// if (false) or if (0) 
{
   //experimental optimization  
}

这种做法在调试、嵌入式设备或个人代码等特定环境中非常有用。

其他回答

一个可能的目的是控制变量范围。由于具有自动存储的变量在超出作用域时被销毁,这也可以使析构函数比其他情况下更早地被调用。

当物体超出范围时,它们会自动被魔法摧毁。

一个原因可能是在新花括号块中声明的任何变量的生命周期都限制在这个块中。我想到的另一个原因是能够在最喜欢的编辑器中使用代码折叠。

其他人已经正确地讨论了范围、RAII等可能性,但既然您提到了嵌入式环境,还有一个潜在的原因:

也许开发人员不相信这个编译器的寄存器分配,或者希望通过限制作用域内自动变量的数量来显式控制堆栈帧的大小。

下面是isInit可能会在堆栈上:

{
   bool isInit;
   (void)isStillInInitMode(&isInit);
   if (isInit) {
     return isInit;
   }
}

如果去掉花括号,isInit的空间可能会在堆栈框架中保留,即使它可能被重用:如果有许多具有类似本地化范围的自动变量,并且堆栈大小有限,这可能是一个问题。

类似地,如果你的变量被分配给了一个寄存器,超出作用域应该会强烈提示这个寄存器现在可以重用了。您必须查看使用和不使用大括号生成的汇编程序,以确定这是否有真正的区别(并对其进行分析—或观察堆栈溢出—以查看这种差异是否真的重要)。

这有时很好,因为它给了你一个新的作用域,在那里你可以更“干净”地声明新的(自动的)变量。

在c++中,这可能不是那么重要,因为你可以在任何地方引入新变量,但也许这个习惯来自C,直到C99才可以这样做。:)

由于c++具有析构函数,因此在作用域退出时自动释放资源(文件、互斥对象等)也很方便,这可以使事情更清晰。这意味着您可以在更短的时间内保留一些共享资源,而不是在方法开始时获取它。