This question already has answers here:
Unnecessary curly braces in C++
(14 answers)
Closed 9 years ago.
I came across one project,where I found some code which I is not understandable to me. I just started with C++, so it seems like a big problem for me. I am providing few lines of my project,which I am not able to understand.
class abc
{
public:
//some stuff
abc();
};
abc::abc()
{
int someflag = 0;
//code
if(someflag == 0)
{
do
{
//few strcpy operations
{ //(My Question)Without any condition braces started
//variable initialization
}
}while(condition);
}
}
Now my questions...
What we can achieve by doing this operation?
What is happening in inside braces of do-while loop?
What is the scope of the initialized variables (I mentioned) inside
do-while loop?
Is it C++11?
Help me to understand this.
What we can achieve by doing this operation?
You introduce a scope block for the variables inside.
What is happening in inside braces of do-while loop?
See above.
What is the scope of the initialized variables (I mentioned) inside do-while loop?
The variables go out of scope at the end of the braces, they're there for that sole reason. One use case I can think of for this is a scoped_lock or something similar to it for multi-threaded applications.
Is it C++11?
No.
Even in C you can open a brace in any point where a statement is permitted.
This allows to declare and use new variables without interferring with the enclosing scope. For example:
... code before ...
{
int i = 0, sum = 0;
while (i < n) {
sum += dothis(data[i++]);
}
dothat(sum);
}
... code after ...
the two variables i and sum have nothing to do with variables with the same name in the enclosing scope: these two variables are created when entering the block and destroyed when exiting the block (while instead n and data are defined outside). This can help readability by avoiding separation between declaration and use or between declaration and initialization (in old C you were not allowed to put a variable declaration right before use... all locals were required to be declared at start of function: an annoying problem if you don't know yet the value to give them).
If you are in C++ and these block-local variables have a class type the constructor is called when entering the block (not when entering the function) and destroyed immediately when exiting the block. This can be very useful for example for locks
{
Lock mylock(resource);
use_resource();
}
Here are your answers:
Ans 1,2. This is used to define a new scope.
Ans 3. The scope of variables end as soon as the control moves out of the block
Ans 4. Probably the coder comes from C background and it is not particular to C++11 as in C, variables can only be declared at the beginning of a new scope.
Please look at THIS and THIS for further reference.
There are five types of scopes in C++
Function
File
Block
Function Prototype
Class
The code which you shared shows 'block scope'
Block scope
Blocks are portions of C++ code contained within curly braces( {....} ). Identifiers declared within a block have block scope and are visible from their points of definition to the end of the innermost containing block. A duplicate identifier name in a block hides the value of an identifier with the same name defined outside the block.
A variable name declared in a block is local to that block. It can be used only in it and the other blocks contained under it.
Related
If I write something like this:
#include <iostream>
int main()
{
using namespace std;
{int n;n=5;} cout<<n;
system("pause");
return 0;
}
The compiler tells me that n is undeclared. Then I tried making it static, but again, the compiler tells me that it is undeclared. Doesn't a variable declated static have program scope? If not, how do I use n in this program?
You're confusing scope with lifetime. Static variables have a lifetime equal to the program's lifetime, but they still follow scoping rules based on where they are declared.
The scope of n is just between the brackets:
{int n;n=5;}
so outside of the block, you have no n variable.
Making it static just makes it's value retain even after you exit the block so that the next time you enter that block again, you can retrieve it's value from the last time you executed that block, but still it's scope is still within the brackets.
A variable declared static in the global scope has its scope limited to the translation unit. A variable declared static within a function has its lifetime set to be the same as the program's, but in this case does not affect its scope. You will have to put cout in the same scope as n was declared in order to use it.
Here the compiler gives error n is undeclared because here "{int n;n=5;}" it is declared in the braces. And braces tells us about the scope of the variable. When ever the scope ends the variable is deleted from the memory.
And for Static and local.
Static : The variable is same like global variable but its value remains constant throughout the application. And the static variable cannot be used on the other page using extern.
Local : The local variables are stored in the stack and they are deleted when they get out of scope.
how do I use n in this program?
using namespace std;
int main()
{
int n; // declare n as int
n=5; // assign it a value
cout << n; // display it.
system("pause");
return 0;
}
Please don't be confuse between scope and life time of a static variable. Scope means where can you access the variable. Life time of variable is duration for which variable stay in memory. In your case,
Scope of x varible is within the curly braces. Life time of x would be program scope.
int main()
{
int x;
int x;
return 0;
}
This snippet will give an error:
error: redeclaration of 'int x'
But this one, works just fine:
int main()
{
while(true)
{
int x;
{...}
}
return 0;
}
Which is the reason why in the second example, declaring x in the loop does not redeclare it every iteration? I was expecting the same error as in the first case.
You're smashing together two related but different concepts and thus your confusion. But it's not your fault, as most of the didactic material on the matter doesn't necessarily make the distinction between the two concepts clear.
Variable scope: This is the region of the source code where a symbol (a variable) is visible.
Object lifetime: this is the time during the runtime of the program that an object exists.
This brings us to other two concepts we need to understand and differentiate between:
A variable is a compile-time concept: it is a name (a symbol) that refers to objects
An object is an "entity" at runtime, an instance of a type.
Let's go back to your examples:
int main()
{
int x{};
int x{};
}
Here you try to declare 2 different variables inside the same scope. Those two variables would have the same name inside the function scope, so when you would "say" the name x (when you would write the symbol x) you wouldn't know to which variable you would refer. So it is not allowed.
int main()
{
while(true)
{
int x{};
}
}
Here you declare one variable inside the while body scope. When you write x inside this scope you refer to this variable. No ambiguity. No problems. Valid code. Note this discussion about declarations and variable scope applies at compile-time, i.e. we are discussion about what meaning has the code that you write.
When we discus object lifetime however we are talking about runtime, i.e. the moment when your compiled binary runs. Yes, at runtime, multiple objects will be created and destroyed in succession. All of these objects are referred by the symbol x inside the while body-scope. But the lifetimes of these objects don't overlap. I.e. when you run your program the first object is created. In the source code it is named x inside the while-body scope. Then the object is destroyed, the loop is re-entered and a new object is created. It is also named x in the source code inside the while-body scope. Then it is destroyed, the while is re-entered, a new object is created and so on.
To give you an expanded view on the matter, consider you can have:
A variable which never refers to an object
{ // not global scope
int a; // <-- not initialized
}
The variable a is not initialized, so an object will never be created at runtime.
An object without a name:
int get_int();
{
int sum = get_int() + get_int();
}
There are two objects returned by the two calls to the function get_int(). Those objects are temporaries. They are never named.
Multiple objects instantiated inside the scope of a variable.
This is an advanced, contrived example, at the fringe of C++. Just showing that it is technically possible:
{
int x;
// no object
new (&x) int{11}; // <-- 1st object created. It is is named `x`. Start of its lifetime
// 1st object is alive. Named x
x.~int(); // <-- 1st object destructed. End of its lifetime
// no object
new (&x) int{24}; // <-- 2nd object created. Also named `x`
// 2nd object alive. Named x
} // <-- implicit end of the lifetime of 2nd object.
The scope of x is the whole block delimited by the curly brackets. However there are two object with different non-overlapping lifetimes inside this scope.
Declarations don't happen at runtime, they happen at compile-time.
In your code int x; is declared once, because it appears in the code once. It doesn't matter if it's in a loop or not.
If the loop runs more than once, x will be created and then destroyed more than once. It's allowed, of course.
In c++, the curly braces represent the beginning {, and end }, of a scope. If you have a scope nested inside another scope, for example a while loop inside a function, then the previously declared variables from the outer scope are available inside the new loop scope.
You are not allowed to declare a variable with the same name inside the same scope twice. That's why the compiler creates the first error
error: redeclaration of 'int x'
But in the case of the loop, the variable is only declared once. It doesn't matter that the loop will reuse that declaration multiple times. Just like a function being called multiple times doesn't create a redeclaration error for the variables it declares.
Variables in loops stay in loops, and are not redeclared. This is because, to the best of my knowledge, Loops are just sets of instructions with jump points, and not actually the same code in the .exe file written over and over again.
If you try to make a for loop:
for(int x = 0; x < 10000; ++x);
The loop just reuses the same variable, then removes the variable after use. This is helpful so that loops, and do{}while(condition)'s can actally hold values, and not just have to redeclare, and reset each variable.
Back to the original question, I am going to ask my own: Why are you trying to redeclare a variable? You could just do this:
int main(void){
int variable = 0;
...
variable = 2;
}
Instead of this:
int main(void){
int variable = 0;
...
int variable = 2;
}
Curly brackets in C/C++ represent blocks of code. These blocks of code do not transfer information to other blocks. I recommend looking further into resources on blocks of code, but one resource has been linked here.
Unlike code that is written in "interpreted languages", variables require declaration. Moreover, your code is read sequentially in compiled languages.
Block example:
while (true) {
int i = 0;
}
This declaration is stored with the block somewhere in memory.
The storage is assigned to an "int" variable type. This data member has a certain memory capacity. Redeclaring, in essence, tries to override information stored in that particular block. These blocks are set aside at compilation time.
Are all variables within a C++ function pre-initialized when the function is called, regardless of where they are declared? I ask this as I would like to know if exiting a function before the entire function has been executed would lead to memory leaks of variables declared after a return statement. For instance:
string oddOrEven(int a)
{
if ((a % 2) != 0)
{
string odd{ "the number is odd" };
return odd;
}
else
{
string even{ "the number is even" };
return even;
}
}
This piece of code is just for demonstration purposes.
If it were an odd number that was handed to the function, would the string even{} never be created? Because if it were to be created, wouldnt that mean that the string will become a memory leak when the function was exited in the first part of the if-else block?
The string even is local to the else block and wouldn't be created if a had been odd.
NOTE: Local variables, even those declared directly inside a function, are NOT auto-initialized; only global variables declared outside all functions are auto-initialized..
REFERENCES:
http://www.tutorialspoint.com/cplusplus/cpp_variable_scope.htm
From the URL below: "A local variable declared inside a conditional (block) will go out of scope at the end of the conditional."
Scope of variables in if statements
Once your program leaves the function oddOrEven(int a), all of the local variables of that function are destroyed and returns your string
If it were an odd number that was handed to the function,the string even{} never be created.
The point that the other answers are trying to address is that ALL local variables including either odd or even are destroyed on exit from the scope in which they are created.
odd (or even) is NOT what is returned from the function. What is returned is a temporary copy of odd or even and the caller knows to delete this copy.
Note: this is ignoring Return Value Optimization (RVO) because that would only make the situation more confusing.
I am trying to optimize a program in C++ I have implemented and a question came in mind...
Where should I declare a variable if I have a repetitive structure using it?
For example:
//1-> int sum;
int matrix[10][10];
for(int i = 0; i < n; i++){
//1-> sum=0;
//2-> int sum=0;
for(int j = 0; j < n; j++)
sum += matrix[i][j];
printf("%d ", sum);
}
So which is better/recommended? Should I declare it at the beginning //->1 outside of the repetitive structure or it is fine if is redeclared //->2 at each iteration?
My guess is that declaration takes a very small time (milliseconds or less) but if you redeclare it in a repetitive structure big enough (or inside multiple structures) each redeclaration will add up to some extra seconds.
For an int it just doesn't matter. For a type with a non-trivial constructor or destructor, under scheme 2 it would be constructed and destroyed each time through the outer loop, and that would be potentially time-consuming.
It doesn't matter. The stack (reserved space in memory) is allocated all together in the beginning of the function/method. If it's an object, the contructor and destructor will be called somewhere in the scope of your loop. But for elemental types, there's absolutely no difference.
As others have already stated, it mostly doesn't matter for an int.
There are only two things to concern yourself with here:
Readability
Scope
If the int is declared right before the for loop rather than as the first line of the for loop, readability is probably about the same. Plus, many compiler's will have a shortcut for jumping straight to a declaration.
As for Scope, if you don't need the variable outside of the loop, putting it inside helps make sure you don't accidentally use it outside the loop in any way. If you do need it outside the loop, you really don't have much choice.
A note on my personal preference which combines both scope and readability issues, when I write code, I prefer having EVERY variable I will use in a given scope declared at the beginning of that scope. Any variable I use in main is declared at the top of main. Any variable used in a function is declared at the top of that function. Any variable used in a loop is declared at the top of that loop. Any variable used in a if statement is declared at the top of that if statement. I personally make very few exceptions. So in your case, if the scope of sum is limited purely to your for loop, I'd declare it as the first variable of the for loop. If sum needs scope outside of the loop, I'd declare it at the top of whatever function you're in and give it a far more descriptive name.
MyClass GlobalVar;
int main()
{
MyClass VarInMain;
}
A couple of things:
Typically, they're allocated in different places. Local variables are allocated on the stack, global variables are allocated elsewhere.
Local variables in main are only visible within main. On the other hand, a global variable may be accessed anywhere.
More differences:
If constructor/destructor of global object throws an exception, then function terminate is called and there is no chance to proceed. For local object, you can catch exception and do something (but it is still tricky to throw from destructor).
Order of construction/destruction of global objects is not well specified. This means, that generally for two global objects you cannot say, which one is constructed first. From the other hand, local objects are created at point of defintion and destructed at end of block in order reverse to order of creation.
Scope... (already mentioned)
In general, it is not a good practice to use global objects without very strong reasons to do so. Using of globals often leads to code which is hard to maintain.
The variable VarInMain is a local variable and can only be used inside the function where it is declared, in your case, the main function. The GlobalVar can be used in every function of your program because it was declared outside of a function. This is called Scope.
Scope. VarInMain can be accessed directly only by code in main. GlobalVar can be accessed directly by code in any function in the file.
A simple example:
int y = 43;
void foo() {
// y is visible here, x is not
}
int main() {
int x = 42;
foo(); // x is visible here, but not when we enter the foo() function
}
A global variable is visible globally, across all functions.
A local variable is visible in the scope in which it is declared only. if you declare a local variable inside main, it will be visible there, yes, but not in functions that are called from main.
VarInMain is accessible only within the main() function. If main() calls another function, that function will not have access to it. This is function scope.
GlobalVar is accessible in every function in the same file. If you put extern MyClass GlobalVar; in a header, then it can be used in any function in files which have or include that declaration. This is global scope.
Another difference: the order of global object initilization is undefined.
For example:
static Integer Global_Integer(5);
static Foo Global_Foo;
As these are objects, the C++ runtime will call their constructors when initializing them, but we can't predict the order in which this will happen.
Another difference:
Global variables will be initialized before the program starts (i.e. main() gets called) whereas the local variables are initialized as execution reaches that point (i.e. just after main is called in the above example).
globals can be used in functions declared outside of main, while anything declared in main, must be passed to another function first.
Another one: The global variables (or variables in any other namespaces) are initialized to (T)0, with T being the type of the variable (in case it's a simple non-class type), arrays and classes are initialized like that for all their elements.
But in my opinion, it's a good idea to explicitly initialize things anyway, and not rely on that zero initialization since it improves readability of the program when the initial value is explicitly mentioned. It's however still useful to know when reading someone else's code, always keeping in mind the compiler will initialize those automatically.
The local variable when it is not declared static isn't automatically initialized. So you have to do any initialization on your own in case T has no constructor doing it for you. Always keep that in mind.
A global variable is accessible to any function. A variable in main acts exactly like any other local variable, and is only accessible to code in main.
Also, if main (or another function) calls itself, the local variables will be copied, but global variables will not.
int x = 0;
void myfunction()
{
x++;
printf("%i ",x);
}
int main()
{
myfunction();
myfunction();
}
This example will output:
1
2
Moving the "int x = 0;" into myfunction will output:
1
1
Because the local variable gets initialised each time myfunction is called.
LOCAL VARIABLE
It is a variable which is declared within a function or within a block. It is accessible only within a function/block in which it is declared.
GLOBAL VARIABLE
It is a variable declared outside all the functions. It is accessible throughout the program.