user1555816
user1555816

Reputation:

Scope within a scope, do or don't?

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"

Upvotes: 3

Views: 378

Answers (5)

Kerrek SB
Kerrek SB

Reputation: 477030

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();
}

Upvotes: 4

Branko Dimitrijevic
Branko Dimitrijevic

Reputation: 52107

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.

Upvotes: 3

bitmask
bitmask

Reputation: 34628

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.

Upvotes: 7

Pete Becker
Pete Becker

Reputation: 76245

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.

Upvotes: 2

anio
anio

Reputation: 9161

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.

Upvotes: 6

Related Questions