45

I mean other than using it when required for functions, classes, if, while, switch, try-catch.

I didn't know that it could be done like this until I saw this SO question.

In the above link, Eli mentioned that "They use it to fold up their code in logical sections that don't fall into a function, class, loop, etc. that would usually be folded up."

What other uses are there besides those mentioned?

Is it a good idea to use curly braces to limit the scope of your variables and expand the scope only if required (working on a "need-to-access" basis)? Or is it actually silly?

How about using scopes just so that you can use the same variable names in different scopes but in the same bigger scope? Or is it a better practise to reuse the same variable (if you want to use the same variable name) and save on deallocating and allocating (I think some compilers can optimise on this?)? Or is it better to use different variable names altogether?

Community
  • 1
  • 1
blizpasta
  • 2,624
  • 3
  • 25
  • 31
  • 2
    Please don't _retag_ your question to include `c#` 2 years later as it greatly affects the answers and comments on this page –  Aug 24 '16 at 23:52

13 Answers13

53

I do if I am using a resource which I want to free at a specific time eg:

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...
}
Adam Pierce
  • 33,531
  • 22
  • 69
  • 89
  • 3
    Yep RAII is the best reason to use "anonymous" scopes instead of creating a new function since the bound scope of the RAII variable is usually very small. – Greg Rogers Oct 30 '08 at 01:42
  • 12
    SerialPort implements IDisposable. You should use a `using` block to ensure the resource is freed. – JDB Nov 07 '12 at 15:28
  • @JDB Question was tagged `c+++` at the time and not `c# so `IDisposable` doesn't apply. Otherwise I totally agree with you –  Aug 24 '16 at 23:51
  • @MickyD Fair enough, though in my defense when I came to it it was also tagged C#. – Adam Houldsworth Aug 30 '16 at 06:51
  • @AdamHouldsworth No worries. Who moved my cheese? :) –  Aug 30 '16 at 08:48
40

I would not use curly braces for that purpose for a couple reasons.

  1. If your particular function is big enough that you need to do various scoping tricks, perhaps break the function into smaller sub-functions.

  2. Introducing braces for scoping to reuse variable names is only going to lead to confusion and trouble in code.

Just my 2 cents, but I have seen a lot of these types of things in other best practice materials.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
agartzke
  • 3,885
  • 6
  • 24
  • 17
  • This is generally my view too - if I need to hide something, i just use `#region` and `#endregion` – Nobody Sep 03 '10 at 09:56
  • I agree, functions should be used for scoping, if you're using tricks like anonymous scopes or #region to make your function easier to understand or write then you should definitely split it up into other functions. – CamW Jun 13 '14 at 08:12
17

C++:

Sometimes you need to introduce an extra brace level of scope to reuse variable names when it makes sense to do so:

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

The code above doesn't compile. You need to make it:

switch (x) {
    case 0:
        {
            int i = 0;
            foo(i);
        }
        break;
    case 1:
        {
            int i = 1;
            bar(i);
        }
        break;
}
J Blaz
  • 783
  • 1
  • 6
  • 26
Greg Rogers
  • 35,641
  • 17
  • 67
  • 94
  • 1
    You should fix the example to use the same variable "i" on both cases. The code compiles fine if you use "i" and "j". – pauloya Oct 18 '10 at 07:55
  • @Paulo it shouldn't compile, you should get an error for jumping across the initialization of i. See Section 6.7#3 (incl note 2) of the standard. – Greg Rogers Oct 18 '10 at 17:34
  • Sorry, I didn't understand what you mean with jumping across the initialization of i, do you have a link to section 6.7#3? It compiled fine on my Snippet Compiler. – pauloya Oct 19 '10 at 07:39
  • @Paulo http://www.csci.csusb.edu/dick/c++std/cd2/stmt.html#stmt.dcl *It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps2) from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (_basic.types_) and is declared without an initializer (_dcl.init_).* Also *2) The transfer from the condition of a switch statement to a case label is considered a jump in this respect.* – Greg Rogers Oct 19 '10 at 13:33
  • Oh, you're talking about C++ ! This code works fine on C# :) – pauloya Oct 19 '10 at 16:09
  • I do use this a lot in C# though when I have repeated variable names in some of the "cases" and I don't think it's appropriate to declare the variable outside the switch. – pauloya Oct 19 '10 at 16:17
15

The most common "non-standard" use of scoping that I use regularly is to utilize a scoped mutex.

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
}

This has many benefits, but the most important is that the lock will always be cleaned up, even if an exception is thrown in the protected code.

Marcin
  • 12,245
  • 9
  • 42
  • 49
15

The most common use, as others have said, is to ensure that destructors run when you want them to. It's also handy for making platform-specific code a little clearer:

#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
    }

Code built for Windows doesn't see the if, only the braces. This is much clearer than:

#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
Graeme Perrow
  • 56,086
  • 21
  • 82
  • 121
6

It can be a boon to code generators. Suppose you have an Embedded SQL (ESQL) compiler; it might want to convert an SQL statement into a block of code that needs local variables. By using a block, it can reuse fixed variable names over and over, rather than having to create all the variables with separate names. Granted, that's not too hard, but it is harder than necessary.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
6

As others have said, this is fairly common in C++ due to the all-powerful RAII (resource acquisition is initialization) idiom/pattern.

For Java programmers (and maybe C#, I don't know) this will be a foreign concept because heap-based objects and GC kills RAII. IMHO, being able to put objects on the stack is the greatest single advantage of C++ over Java and makes well-written C++ code MUCH cleaner than well-written Java code.

Drew Hall
  • 28,429
  • 12
  • 61
  • 81
5

I only use it when I need to release something by the means of RAII and even then only when it should be released as early as I possibly can (releasing a lock for example).

Jasper Bekkers
  • 6,711
  • 32
  • 46
3

Programming in Java I have quite often wanted to limit scope within a method, but it never occurred to me to use a label. Since I uppercase my labels when using them as the target of a break, using a mixed case labeled block like you have suggested is just what I have wanted on these occasions.

Often the code blocks are too short to break out into a small method, and often the code in a framework method (like startup(), or shutdown()) and it's actually better to keep the code together in one method.

Personally I hate the plain floating/dangling braces (though that's because we are a strict banner style indent shop), and I hate the comment marker:

// 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

We considered using "if(true) {" because the Java spec specifically says these will be optimized away in compilation (as will the entire content of an if(false) - it's a debugging feature), but I hated that in the few places I tried it.

So I think your idea is a good one, not at all silly. I always thought I was the only one who wanted to do this.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
1

Yes, I use this technique because of RAII. I also use this technique in plain C since it brings the variables closer together. Of course, I should be thinking about breaking up the functions even more.

One thing I do that is probably stylistically controversial is put the opening curly brace on the line of the declaration or put a comment right on it. 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);
  }
}
piyo
  • 784
  • 5
  • 14
0

I agree with agartzke. If you feel that you need to segment larger logical code blocks for readability, you should consider refactoring to clean up busy and cluttered members.

Peter
  • 1,488
  • 2
  • 17
  • 23
0

It has its place, but I don't think that doing it so that $foo can be one variable here and a different variable there, within the same function or other (logical, rather than lexical) scope is a good idea. Even though the compiler may understand that perfectly, it seems too likely to make life difficult for humans trying to read the code.

Dave Sherohman
  • 45,363
  • 14
  • 64
  • 102
0

The company I'm working at has a static analysis policy to keep local variable declarations near the beginning of a function. Many times, the usage is many lines after the first line of a function so I cannot see the declaration and the first reference at the same time on the screen. What I do to 'circumvent' the policy is to keep the declaration near the reference, but provide additional scope by using curly braces. It increases indentation though, and some may argue that it makes the code uglier.

blizpasta
  • 2,624
  • 3
  • 25
  • 31