3

Although the example below compiles fine except for the last line with the error, I'd like to know the ins and outs of this 'scoping' within a scope? Also the terminology of this, if any.

Consider these brackets:

void func()
{

    int i = 0;

    { // nice comment to describe this scope

        while( i < 10 )
            ++i;

    }

    { // nice comment to describe this scope

        int j= 0;
        while( j< 10 )
            ++j;

    }

    i = 0; // OK
    // j = 0; // error C2065

}

consider this:

error C2065: 'j' : undeclared identifier

edit: Accepted answer is from bitmask, although I think everyone should place it in the context of anio's answer. Especially, quote: "perhaps you should break your function into 2 functions"

Community
  • 1
  • 1
  • Just as a suggestion: The first `while` doesn't need a separate scope, since its body is already in a separate scope and there's nothing else leaking from it. The second scope may make sense if the `j` is needed at all; otherwise it should be a `for` loop (without the immediately ambient extra scope). – Kerrek SB Aug 23 '12 at 22:13
  • @KerrekSB: Also setting both vars to 0 isn't needed. Hence, the entire function scope isn't needed. Just fancied it up a bit, ;). as [ void func(){{}{}} ] would have left my question out in the blue and this makes sense even to newbies. –  Aug 23 '12 at 22:22
  • BTW, an empty scope is an ambient scope? Is just a semi-colon [ while(1); // ouch ] an ambient scope too? –  Aug 23 '12 at 22:23
  • No, the `;` scope is a *sub*-scope, not an ambient scope! – Kerrek SB Aug 23 '12 at 22:26

5 Answers5

7

Do. By all means!

Keeping data as local as possible and as const as possible has two main advantages:

  • side effects are reduced and the code becomes more functional
  • with complex objects, destructors can be be invoked early within a function, as soon as the data is not needed any more

Additionally, this can be useful for documentation to summarise the job a particular part of a function does.

I've heard this being referred to as explicit or dummy scoping.

bitmask
  • 32,434
  • 14
  • 99
  • 159
6

I personally don't find much value in adding additional scoping within a function. If you are relying on it to separate parts of your function, perhaps you should break your function into 2 functions. Smaller functions are better than larger ones. You should strive to have small easily understood functions.

The one legitimate use of scopes within a function is for limiting the duration of a lock:

int doX() 
{

 // Do some work

  { 
  //Acquire lock


  } // Lock automatically released because of RAII
}

The inner scope effectively limits the code over which the lock is held. I believe this is common practice.

anio
  • 8,903
  • 7
  • 35
  • 53
4

Yes, definitely - it's a great habit to always keep your variables as local as possible! Some examples:

for (std::string line; std::getline(std::cin, line); )     // does not
{                                                          // leak "line"
    // process "line"                                      // into ambient
}                                                          // scope

int result;

{                                        // putting this in a separate scope
    int a = foo();                       // allows us to copy/paste the entire
    a += 3;                              // block without worrying about
    int b = bar(a);                      // repeated declarators
    result *= (a + 2*b);
}

{                                        // ...and we never really needed
    int a = foo();                       // a and b outside of this anyway!
    a += 3;
    int b = bar(a);
    result *= (a + 2*b);
}

Sometimes a scope is necessary for synchronisation, and you want to keep the critical section as short as possible:

int global_counter = 0;
std::mutex gctr_mx;

void I_run_many_times_concurrently()
{
    int a = expensive_computation();

    {
        std::lock_guard<std::mutex> _(gctr_mx);
        global_counter += a;
    }

    expensive_cleanup();
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
3

The explicit scoping is usually not done for commenting purposes, but I don't see any harm in doing it if you feel it makes your code more readable.

Typical usage is for avoiding name clashes and controlling when the destructors are called.

Community
  • 1
  • 1
Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167
2

A pair of curly braces defines a scope. Names declared or defined within a scope are not visible outside that scope, which is why j is not defined at the end. If a name in a scope is the same as a name defined earlier and outside that scope, it hides the outer name.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165