What are additional { } used for?

Pages: 12
Hi! I am quite new to C and C++. Today I saw the following thing:

1
2
3
4
5
6
7
8
9
10
#include "new.h"
Fl_Window *window_new=(Fl_Window *)0;

Fl_Window* main() {
  { 
    window_new = new Fl_Window(315, 405, "window_main");
    window_new->end();
  } // Fl_Window* window_new
  return window_new;
}


What are these additional { } called (So I can do some googling about them) and what are they used for? I know this question might be dumb and maybe if I read some more about c++ I will occasionally learn what this is but right now I am focusing more on FLTK and I just want to know what these brackets are for. Thank you in advance!
They allow you to manually create an additonal scope. They're just like any other sets of braces, really.
It's the scope operator, a { marks the beginning of a scope, and a } marks the end. Resources that you didn't create using "new" will automatically be destroyed at the end of their scope.
ie:
1
2
3
4
{
int i = 0;
}
i = 10; //Error, i got destroyed because its scope ended. 


In this case I have no idea what it is being used for since window_new is a global variable, and will be unaffected by the end-of-scope. Perhaps it's for readability?
Also, if you need to google them look for "C++ braces". I don't think they have a specific "C++ name".
Actualy, they do! They're called a "fake block", becouse they make the program htink it's some other block and therefore destroys all variables local to that block, while it's actualy the same block.
Why fake block? It IS a new block. And the program has no say in this, things like scopes only exist for the compiler.

The example given looks kinda horrible though.

It's the scope operator

This :: is the scope operator. {} is just a block.
Last edited on
scope resolution operator, I think you'll find.

I've never made a new scope just to destroy some variables, I can't imagine I would unless I suddenly turned really fanatic about 'wasting' a couple bytes of memory, and if it is more then that perhaps you should start splitting the function up.
@Zephilinox I think one of the most common usage of this is when you need to enforce that mutexes are released properly in multithreaded programs. It can also be used in rendering functions to make sure the matrix stack is popped properly (Or in any program that has heavy stack usage for that matter).

@hanst I guess I should have said "a" scope operator.
I knew about the mutex's, but not the stack..usage..thingymabob
I've never made a new scope just to destroy some variables, I can't imagine I would unless I suddenly turned really fanatic about 'wasting' a couple bytes of memory
Memory isn't the only resource. In general, objects should have as small a scope and life time as practically possible.
I know, I declare variables as late as possible in my function, but making a while new scope (and subsequently an extra tab of formatting) seems ridiculous 99% of the time
I've never made a new scope just to destroy some variables, I can't imagine I would unless I suddenly turned really fanatic about 'wasting' a couple bytes of memory
What if the object in question isn't a couple bytes long, but actually a couple hundred million bytes long? In fact, creating a new block is the only way to fine-tune the lifetime of standard containers.
Unless you allocate them dynamically, but that has problems of its own.

@Zephilinox I think one of the most common usage of this is when you need to enforce that mutexes are released properly in multithreaded programs.
Exactly. Auto-locking mutexes is IMO the single best thing about RAII. It's just an awesome way to guarantee correctness of thread synchronization.
regardless of the length, I can't imagine the function going on for any longer than needed, if it did I'm sure it could be split up, or the variable declared later.

do you have any examples?
Perhaps in a complex recursive function that goes quite deep? You wouldn't want objects on the stack for long, especially since the function addresses themselves will take up even more stack space.
closed account (zb0S216C)
As Bjarne Stroustup said in The C++ Programming Language:

Bjarne Stroustrup wrote:
"4.10 Advice [dcl.advice]
[1] Keep scopes small; ยง4.9.4."


Wazzak
Last edited on
wow, I can't believe you're geeky enough to be able to quote from his book as if it was a bible
so kewl!

but regardless, you can keep it small without 'artificial' scopes can't you? sigh I give up arguing about it :3
do you have any examples?
Stream is a class that receives buffers from the application, does something with them, and writes the result to the file system. However, it has an internal buffer such that the state of the output file is undefined while the associated Stream exists*.
f() creates a Stream and writes to it, and once its done writing, it needs to read the resulting file.
The only two ways to do this is to create either a new function or a new block around the Stream. The generated code is likely to be identical, but a new block is just more convenient. Assuming worst case optimizations, the block is preferable because it doesn't involve creating a new stack frame and jumping to a different function.

* If this example sounds contrived, it's not. This is exactly how I wrote a class that implements a gzipped log. It was the most natural way to do it to maximize compression ratio.
Last edited on
I can't imagine


Lacking the imagination to think of a good reason does not mean that a good reason does not exist; arguing from a position of ignorance is one thing, but when ignorance is the argument, it's time to stop.
that's why I asked for examples, and I am ignorant, I admit, about things I don't know.
For something less contrived, I often find myself doing this when prototyping

1
2
3
4
5
6
7
stuff;
stuff
{
    std::lock_guard<std::mutex> lk(io_mutex);
    std::cout << "some debug  value " << var << " and another " << var << '\n';
}
more stuff;


of course these bits get replaced by proper logging library calls later on, but even in production I have a few blocks for the sake of locking hanging around.
I read somewhere that the extra brackets could be a trick to get destructors executed, where they normally wouldn't have been executed.
F.e. when the main is ended with exit() or abort() or terminate() ... if all the statements before are placed within additional brackets, then the destructors are called ... otherwise not.
Last edited on
Pages: 12