In programming, curly braces (the { and } characters) are used in a variety of ways. In C/C++, they are used to signify the start and end of a series of statements. In the following expression, everything between the { and } are executed if the variable mouseDOWNinText is true.
Its not so disturbing when you consider that braces aren't special cased in the C grammar. They group statements so they can be used together where a statement is needed. From the grammar's perspective the "normal" way is without braces.
Without curly braces only first statement consider in scope so statement after if condition will get executed even if there is no curly braces. But it is Highly Recommended to use curly braces. Because if the user (or someone else) ever expands the statement it will be required.
These brackets define important constructs in a programming language. For example, in C and languages influenced by C, "{}" denote a code block while "[]" refers to an array subscript. In Perl, the "<>" is referred to as the filehandle operator for reading from and writing to files.
It's sometimes nice since it gives you a new scope, where you can more "cleanly" declare new (automatic) variables.
In C++
this is maybe not so important since you can introduce new variables anywhere, but perhaps the habit is from C
, where you could not do this until C99. :)
Since C++
has destructors, it can also be handy to have resources (files, mutexes, whatever) automatically released as the scope exits, which can make things cleaner. This means you can hold on to some shared resource for a shorter duration than you would if you grabbed it at the start of the method.
One possible purpose is to control variable scope. And since variables with automatic storage are destroyed when they go out of scope, this can also enable a destructor to be called earlier than it otherwise would.
The extra braces are used to define the scope of the variable declared inside the braces. It is done so that the destructor will be called when the variable goes out of scope. In the destructor, you may release a mutex (or any other resource) so that other could acquire it.
In my production code, I've written something like this :
void f()
{
//some code - MULTIPLE threads can execute this code at the same time
{
scoped_lock lock(mutex); //critical section starts here
//critical section code
//EXACTLY ONE thread can execute this code at a time
} //mutex is automatically released here
//other code - MULTIPLE threads can execute this code at the same time
}
As you can see, in this way, you can use scoped_lock
in a function and at the same time, can define its scope by using extra braces. This makes sure that even though the code outside the extra braces can be executed by multiple threads simultaneously, the code inside the braces will be executed by exactly one thread at a time.
As others have pointed out, a new block introduces a new scope, enabling one to write a bit of code with its own variables that don't trash the namespace of the surrounding code, and doesn't use resources any longer than necessary.
However, there's another fine reason for doing this.
It is simply to isolate a block of code that achieves a particular (sub)purpose. It is rare that a single statement achieves a computational effect I want; usually it takes several. Placing those in a block (with a comment) allows me tell the reader (often myself at a later date):
e.g.
{ // update the moving average
i= (i+1) mod ARRAYSIZE;
sum = sum - A[i];
A[i] = new_value;
sum = sum + new_value;
average = sum / ARRAYSIZE ;
}
You might argue I should write a function to do all that. If I only do it once, writing a function just adds additional syntax and parameters; there seems little point. Just think of this as a parameterless, anonymous function.
If you are lucky, your editor will have a fold/unfold function that will even let you hide the block.
I do this all the time. It is great pleasure to know the bounds of the code I need to inspect, and even better to know that if that chunk isn't the one I want, I don't have to look at any of the lines.
One reason could be that the lifetime of any variables declared inside the new curly braces block is restricted to this block. Another reason that comes to mind is to be able to use code folding in the favourite editor.
This is the same as an if
(or while
etc..) block, just without if
. In other words, you introduce a scope without introducing a control structure.
This "explicit scoping" is typically useful in following cases:
using
.Example 1:
{
auto my_variable = ... ;
// ...
}
// ...
{
auto my_variable = ... ;
// ...
}
If my_variable
happens to be a particularly good name for two different variables that are used in isolation from each other, then explicit scoping allows you to avoid inventing a new name just to avoid the name clash.
This also allows you to avoid using my_variable
out of its intended scope by accident.
Example 2:
namespace N1 { class A { }; }
namespace N2 { class A { }; }
void foo() {
{
using namespace N1;
A a; // N1::A.
// ...
}
{
using namespace N2;
A a; // N2::A.
// ...
}
}
Practical situations when this is useful are rare and may indicate the code is ripe for refactoring, but the mechanism is there should you ever genuinely need it.
Example 3:
{
MyRaiiClass guard1 = ...;
// ...
{
MyRaiiClass guard2 = ...;
// ...
} // ~MyRaiiClass for guard2 called.
// ...
} // ~MyRaiiClass for guard1 called.
This can be important for RAII in cases when the need for freeing resources does not naturally "fall" onto boundaries of functions or control structures.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With