Krapow
Krapow

Reputation: 641

What is the purpose of {} without any keyword before?

Today, i spent 4 hours debugging a little mistake:

while (++i < nb); //Notice this semicolon that i put by mistake
{
    do_stuff();
}

I didn't know why the do_stuff didn't execute enough times. When I saw my mistake, I wondered: Why the hell would someone enclose codes into braces in the middle of a function?? Can someone have an explanation? Is that the way C languages evolved ? (I know the BNF of C contains some weird things due to retro compatibility reasons) And do you think pre incrementation in a loop is a bad thing, that I should write like above instead?

while (i < nb)
{
    do_stuff();
    i += 1;
}

Upvotes: 1

Views: 282

Answers (5)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122133

Why the hell would someone enclose codes into braces in the middle of a function??

Thats not a strange think at all, but it introduces a scope, as in the following example:

void foo () {
    int a;
    {          // start a new scope
        int b = 1;
        std::cout << b << std::endl;
    }         // end of scope, i.e. b is out of scope now
    std::cout << a << std::endl;
    std::cout << b << std::endl; // error: unknown variable b !!
    double b = 0.0;              // just fine: declares a new variable
}

You can use it to localize the accessability of variables inside functions. In the example b is a temporary and by putting its declaration inside a local scope I avoid spamming the function scope with variable names.

Upvotes: 7

Slava
Slava

Reputation: 44238

I believe most common use is together with RAII:

{
   std::lock_guard<std::mutex> lock(mutex);
   // code inside block is under mutex lock
}
// here mutex is released

Upvotes: 5

nwp
nwp

Reputation: 9991

Local scopes make sense to limit the life time and scope of objects. They are vital to switch/case statements:

switch (i){
case 1:
    std::string s;
case 2:
    //does s exist or not? depends on the value of i
}

C++ says this is straight-up illegal. To fix this you introduce a local scope:

switch (i){
case 1:
{
    std::string s;
}//the lifetime of s ends here
case 2:
    //s is inaccessible
}

Now s is limited to its scope and you solved the problem of s being sometimes defined.

You can add as many local blocks as you want, for example this is fine:

int main(){{{{{{{{{{
}}}}}}}}}}

Upvotes: 1

Shawnse
Shawnse

Reputation: 51

{<statement>*} (* means zero or more) are code blocks in C/C++ and are treated as a single statement. Statements are things like if (<expression>) <statement> (note: this is a recursive statement). Another statement could be <expression>;.

Also {} generates a new scope.

This is also the reason why you can give multiple statements in an if statement.

If it helps, you can think of them as inline functions, with access to the current scope. (Not a correct way to view it, but close enough)

Look at @tobi303's answer for an example.

Upvotes: 0

marcinj
marcinj

Reputation: 49976

You might want to put all the logic inside the while and omit body intentionally. Some compilers will warn you about that, ie. clang:

main.cpp:18:17: warning: while loop has empty body [-Wempty-body]
while (++i < nb); //Notice this semicolon that i put by mistake
                ^
main.cpp:18:17: note: put the semicolon on a separate line to silence this warning

Introducing of local scopes like:

{
   SomeClass aa;
   // some logic
}

is also not uncommon, you might want, in above someone might want aa destructor to be called before the closing braces - ie. it will release some resource.

Upvotes: 5

Related Questions