代码之家  ›  专栏  ›  技术社区  ›  blizpasta

是否使用花括号来附加范围?[关闭]

  •  36
  • blizpasta  · 技术社区  · 17 年前

    我的意思是,除了在函数、类、if、while、switch、try catch需要时使用它之外。

    我不知道能做得像 this until I saw this SO question .

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

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

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

    如何使用范围,以便您可以在不同的范围内使用相同的变量名,但在相同的更大范围内?或者更好的做法是重用相同的变量(如果您想使用相同的变量名)并保存在释放和分配上(我认为一些编译器可以对此进行优化?)?还是最好同时使用不同的变量名?

    13 回复  |  直到 9 年前
        1
  •  48
  •   Adam Pierce    17 年前

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

    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...
    }
    
        2
  •  39
  •   abatishchev Karl Johan    14 年前

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

    1. 如果您的特定函数足够大,以至于需要执行各种作用域技巧,那么可以将该函数分解为较小的子函数。

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

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

        3
  •  16
  •   Marcin    17 年前

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

    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
    }
    

    这有许多好处,但最重要的是,即使在受保护的代码中抛出异常,锁也将始终被清除。

        4
  •  15
  •   J Blaz Artem Kabakov    9 年前

    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;
    }
    
        5
  •  11
  •   Graeme Perrow    17 年前

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

    #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
    
        6
  •  6
  •   Jonathan Leffler    17 年前

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

        7
  •  6
  •   Drew Hall    17 年前

    正如其他人所说的,这在C++中是相当普遍的,因为全功能RAII(资源获取是初始化)习惯用法/模式。

    对于Java程序员(也可能是C,我不知道),这将是一个外来概念,因为基于堆的对象和GC杀死RAII。IMHO,能够将对象放在堆栈上是C++在Java上最大的优点,并使编写良好的C++代码比编写好的Java代码更干净。

        8
  •  5
  •   Jasper Bekkers    17 年前

    我只在需要通过raii释放某个东西时使用它,甚至在需要尽可能早地释放它时使用(例如释放一个锁)。

        9
  •  3
  •   L. Cornelius Dol    17 年前

    在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)的整个内容——它是一个调试特性),但我讨厌在我尝试过的几个地方。

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

        10
  •  1
  •   piyo    17 年前

    是的,我使用这种技术是因为RAII。我也用这种方法 C 因为它使变量更紧密地结合在一起。当然,我应该考虑更进一步地分解函数。

    我做的一件事很可能在风格上有争议,就是把开场花括号放在声明的行上,或者在上面写上评论。 I want to decrease the amount of wasted vertical space. This is based on the Google C++ Style Guide recommendation. .

    /// 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);
      }
    }
    
        11
  •  0
  •   Peter    17 年前

    我同意阿加茨克的观点。如果您觉得为了可读性需要分割更大的逻辑代码块,那么您应该考虑重构以清除繁忙和混乱的成员。

        12
  •  0
  •   Dave Sherohman    17 年前

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

        13
  •  0
  •   blizpasta    15 年前

    我工作的公司有一个静态分析策略,可以将局部变量声明保存在函数的开头附近。很多时候,函数的第一行后面的用法是多行的,所以我不能在屏幕上同时看到声明和第一个引用。我所做的“规避”策略是将声明保持在引用附近,但使用大括号提供额外的范围。但是,它增加了缩进,一些人可能认为这会使代码更丑。