43

我的意思是在函数、类、if、while、switch、try-catch 需要时使用它。

在我看到这个 SO question 之前,我不知道它可以这样做。

在上面的链接中,Eli 提到“他们使用它来将代码折叠在不属于通常会折叠的函数、类、循环等的逻辑部分中。”

除了上面提到的还有什么其他用途?

使用花括号来限制变量的范围并仅在需要时扩展范围是一个好主意(在“需要访问”的基础上工作)?还是真的很傻?

如何使用范围,以便您可以在不同的范围内使用相同的变量名,但在相同的更大范围内?或者重复使用相同的变量(如果你想使用相同的变量名)并节省解除分配和分配(我认为一些编译器可以对此进行优化?)是更好的做法吗?还是完全使用不同的变量名更好?

4

13 回答 13

52

如果我正在使用我想在特定时间释放的资源,我会这样做,例如:

void myfunction()
{
  {
  // Open serial port
     SerialPort port("COM1", 9600);
     port.doTransfer(data);
  } // Serial port gets closed here.

  for(int i = 0; i < data.size(); i++)
     doProcessData(data[i]);
  etc...
}
于 2008-10-30T01:35:23.267 回答
39

出于几个原因,我不会为此使用花括号。

  1. 如果您的特定功能足够大以至于您需要执行各种范围技巧,则可能会将功能分解为更小的子功能。

  2. 引入大括号来重用变量名只会导致代码混乱和麻烦。

只是我的 2 美分,但我在其他最佳实践材料中看到了很多这类东西。

于 2008-10-30T01:34:55.640 回答
17

C++

有时你需要引入一个额外的大括号级别的范围来重用变量名,当这样做有意义时:

switch (x) {
    case 0:
        int i = 0;
        foo(i);
        break;
    case 1:
        int i = 1;
        bar(i);
        break;
}

上面的代码无法编译。你需要做到:

switch (x) {
    case 0:
        {
            int i = 0;
            foo(i);
        }
        break;
    case 1:
        {
            int i = 1;
            bar(i);
        }
        break;
}
于 2008-10-30T01:40:20.120 回答
16

我经常使用的最常见的“非标准”作用域使用是使用作用域互斥锁。

void MyClass::Somefun()
{
    //do some stuff
    {
        // example imlementation that has a mutex passed into a lock object:
        scopedMutex lockObject(m_mutex); 

        // protected code here

    } // mutex is unlocked here
    // more code here
}

这有很多好处,但最重要的是,即使在受保护的代码中抛出异常,锁也会一直被清除。

于 2008-10-30T13:25:24.410 回答
14

正如其他人所说,最常见的用途是确保析构函数在您需要时运行。它还有助于使特定于平台的代码更加清晰:

#if defined( UNIX )
    if( some unix-specific condition )
#endif
    {
        // This code should always run on Windows but 
        // only if the above condition holds on unix
    }

为 Windows 构建的代码看不到 if,只有大括号。这比:

#if defined( UNIX )
    if( some unix-specific condition ) {
#endif
        // This code should always run on Windows but 
        // only if the above condition holds on unix
#if defined( UNIX )
    }
#endif
于 2008-10-30T13:34:25.297 回答
6

它可以是代码生成器的福音。假设您有一个嵌入式 SQL (ESQL) 编译器;它可能希望将 SQL 语句转换为需要局部变量的代码块。通过使用块,它可以反复重用固定的变量名称,而不必创建具有单独名称的所有变量。当然,这不是太难,但比必要的难。

于 2008-10-30T01:36:04.497 回答
6

正如其他人所说,由于功能强大的 RAII(资源获取是初始化)习语/模式,这在 C++ 中相当普遍。

对于 Java 程序员(也许还有 C#,我不知道)这将是一个陌生的概念,因为基于堆的对象和 GC 会杀死 RAII。恕我直言,能够将对象放入堆栈是 C++ 优于 Java 的最大单一优势,并且使编写良好的 C++ 代码比编​​写良好的 Java 代码更干净。

于 2008-10-30T01:56:53.690 回答
5

我只在需要通过 RAII 释放某些东西时才使用它,即使那样,也只有在应该尽可能早地释放它时(例如释放锁)。

于 2008-10-30T01:36:54.887 回答
3

用 Java 编程我经常想限制方法内的范围,但我从未想过要使用标签。由于我在使用它们作为中断目标时将标签大写,因此使用混合大小写标记的块就像您建议的那样,这正是我在这些场合想要的。

通常代码块太短而无法分解成一个小方法,而且通常是框架方法中的代码(如 startup() 或 shutdown()),实际上最好将代码放在一个方法中。

就我个人而言,我讨厌普通的浮动/悬空大括号(尽管那是因为我们是一家严格的横幅样式缩进店),我讨厌评论标记:

// yuk!
some code
{
scoped code
}
more code

// also yuk!
some code
/* do xyz */ {
    scoped code
    }
some more code

// this I like
some code
DoXyz: {
    scoped code
    }
some more code

我们考虑使用“if(true) {”,因为 Java 规范明确指出这些将在编译中被优化(if(false) 的全部内容也将被优化 - 这是一个调试功能),但我讨厌在少数地方我尝试过这个。

所以我认为你的想法很好,一点也不傻。我一直认为我是唯一一个想做这件事的人。

于 2008-11-01T20:21:35.267 回答
1

是的,我使用这种技术是因为 RAII。我也在纯C中使用这种技术,因为它使变量更接近。当然,我应该考虑更多地分解功能。

我做的一件可能在风格上引起争议的事情是将左花括号放在声明的行上或在其上放置评论。我想减少浪费的垂直空间。这是基于 Google C++ Style Guide 推荐的。.

/// c++ code
/// references to boost::test
BOOST_TEST_CASE( curly_brace )
{
  // init
  MyClass instance_to_test( "initial", TestCase::STUFF ); {
    instance_to_test.permutate(42u);
    instance_to_test.rotate_left_face();
    instance_to_test.top_gun();
  }
  { // test check
    const uint8_t kEXP_FAP_BOOST = 240u;
    BOOST_CHECK_EQUAL( instance_to_test.get_fap_boost(), kEXP_FAP_BOOST);
  }
}
于 2008-11-01T04:38:06.170 回答
0

我同意阿加茨克的观点。如果您觉得需要对较大的逻辑代码块进行分段以提高可读性,则应考虑重构以清理繁忙和杂乱的成员。

于 2008-10-30T01:51:37.680 回答
0

它有它的位置,但我不认为这样做以便 $foo在同一函数或其他(逻辑,而不是词法)范围内可以是一个变量,而另一个变量在那里是一个主意尽管编译器可能完全理解这一点,但对于试图阅读代码的人类来说,这似乎太难了。

于 2008-10-30T02:38:17.477 回答
0

我工作的公司有一个静态分析策略,可以将局部变量声明保持在函数的开头附近。很多时候,函数的第一行之后的用法是很多行,所以我无法在屏幕上同时看到声明和第一个引用。我为“规避”该政策所做的是将声明保持在引用附近,但通过使用花括号来提供额外的范围。虽然它增加了缩进,有些人可能会争辩说它使代码更难看。

于 2010-09-03T17:27:42.290 回答