Could someone exactly explain the concept of scope and life of variable in C. Is it different in C++? I'm confused between scope and life.
"Scope" of a variable is a region of source code, where you can refer to that variable.
"Lifetime" is how long it exists during the program execution.
By default the lifetime of a local variable is the same as its scope:
void foo()
{
int x = 123;
cout << x << endl;
x += 1;
}
int main(){ foo(); foo(); foo(); }
Here, each time foo is called a new x is created (space is reserved for it on the stack), and when the execution leaves the block where x was declared, x is destroyed (which for int just means that the space that was reserved, now is freed for reuse).
In contrast:
void foo()
{
static int x = 123;
cout << x << endl;
x += 1;
}
int main(){ foo(); foo(); foo(); }
Here, since x is declared static, space is reserved for x before the program execution even begins. x has a fixed location in memory, it's a static variable. And C++ has special rules about the initialization of such a variable: it happens the first time the execution passes through the declaration.
Thus, in the first call of foo this x is initialized, the output statement displays 123, and the increment increases the value by 1. In the next call the initialization is skipped (it has already been performed), the value 124 is output, and the value is incremented again. So on.
The lifetime of this x is from start of execution to end of execution.
Scope is the region where the variable is accessible.
Life time is the time span during which an object remains valid.
An simple example:
#include <iostream.h>
void doSomething()
{
x = 5; //Error! Not Accessible
}
int main()
{
int x = 4;
std::cout<< x << endl;
{
int x = 2;
cout << x << endl;
}
doSomething();
std::cout<< x << endl;
return 0;
}
The above gives the output:
4
2
4
In above program,
lifetime of variable x = 4 is throughout the main, i.e: It remains alive throughout the execution of the main, Also it is accessible within the main, that is its scope. Note that it is not accessible in the function because it is beyond the scope of the variable x.
while scope and lifetime of variable x = 2 is within the enclsing braces{ } inside the main.
The scope of a variable is determined at compilation time. It is the region in the program where the same object that is defined through the definition is accessible through that identifier.
The lifetime of an object is a feature that is defined at runtime, through the flow of execution. An object can be accessed through a pointer even if the variable through which it was defined is not in scope.
void f(char *a) {
*a = 'f';
}
void g(void) {
char aChar = ' ';
f(&aChar);
}
Here the scope of variable aChar (the identifier) is the body of g. During the execution of g the lifetime of the object expands to the execution of f. Using the identifier aChar inside f would be illegal, the compiler would tell you something like "unknown indetifier aChar in function f". Using a pointer to that object as done above is completely legal.
The scope of a variable refers to the extent to which different parts of a program have access to the variable.
Variables can be declared as:
Inside a function which is called local variables or internal variables.
Outside of all functions which is called global variables or external variables and lifetime or "extent" extends across the entire run of the program.
Here is detailed tutorial about variables with examples : What is variable in C
Related
class Entity {
//attributes
public:
float X, Y;
Entity() {
X = 0;
Y = 0;
cout << "Created Entity!" << endl;
}
~Entity() {
cout << "Entity Destroyed!" << endl;
}
void Print() {
cout << X << ", " << Y << endl;
}
};
void func() {
Entity e;
e.Print();
}
int main()
{
func();
cout << "b";
}
So I'm kinda having trouble understanding what exactly is happening here, I don't understand when and how e is out of scope. func creates e and then calls the method function but all that only gets executed when I call func in main right? So only when I call func in main e gets created and the method gets called but how exactly is it ever out of scope?
Like can someone please try to explain this like I'm a 5 year old? The entity only gets created when func gets called in main right? When could e ever be out of scope?
I don't understand when and how e is out of scope
The scope of e is everything from its declaration to the end of its enclosing block scope:
void func()
{ // start of block scope
Entity e; // e created in the enclosing block scope here
e.Print();
} // end of block scope, e (and any other automatic locals) destroyed
but all that only gets executed when I call func in main right?
Now you're mixing up two things:
scope is the section of the source code where e is a valid identifier (and refers to the same object, in case you have other variables with the same name in other code). This is static, it's all known at compile time.
control flow is what when func is actually executed, enters its block scope, executes the statements in the function body, and finally exits block scope (destroying any automatic local objects at the same time). This happens at runtime, and is dynamic (in the sense that it might depend on conditional logic, or input).
So only when I call func in main e gets created and the method gets called but how exactly is it ever out of scope?
It has automatic scope, so its scope ends when the enclosing block does. For e, that's when func has finished executing and before control returns to main.
... When could e ever be out of scope?
Try referring to e in main after the call to func. Does it compile?
No, because e isn't an identifier in this scope.
What's the alternative? Every large program would accumulate every variable name that was ever used in the global namespace. It would rapidly become unmanageable, and in fact that's exactly the reason we use local variables instead of globals.
Note that we can disentangle scope from lifetime just by returning something. If we choose something with dynamic lifetime:
std::unique_ptr<Entity> foo()
{ // block begins
std::unique_ptr<Entity> e; // e scope begins
e.reset( new Entity ); // *e lifetime begins
e->Print();
return std::move(e); // *e moves to return value
} // e destroyed
int main()
{
auto f = foo(); // *e is now called *f
f->Print();
} // f destroyed and deletes *f
You can see there's an anonymous object (created by new), which is pointed at first by *e and then by *f
e has the same (block) scope as before
e has the same (automatic) lifetime, so it is destroyed when it goes out of scope
the object originally known as *e is handed off to f, and keeps existing. It still doesn't have an identifier of its own that could be bound to a scope.
f also has block scope & automatic lifetime
*f (the dynamic object formerly known as *e) is destroyed along with f only because we didn't move it elsewhere.
e is created once you called func and will be destroyed when that function finishes its execution.
So its scope is only within that function braces.
From your comments I think you're having a little trouble with what scope means in this context. It is true that e is created after a call to func in main. However, in C++ one thing the {} symbols denote scope. Here e is declared within the scope of func(inside the brackets of the function) meaning the scope of e is locale to the function. This means that once func returns that variable will go out of scope and thus the destructor is called since it is not longer accessible. This scoping is also why you cannot use e outside of func even though the function is called from main.
The code is :
#include <iostream>
using namespace std;
class A
{
public:
A() { cout << "A::A" << endl; }
~A() { cout << "A::~" << endl; }
};
class B
{
public:
B() { cout << "B::B" << endl; }
~B() { cout << "B::~" << endl; }
};
int main()
{
B b;
static A a;
return 0;
}
The output is :
B::B
A::A
B::~
A::~
The scope of non-static object b and the scope of static object a ends at the end of main() function.
Question : Why is the order of constructors is same as the order of destructors ?
Static local variables will be destroyed at program exit.
The destructor for a block-scope static variable is called at program exit, but only if the initialization took place successfully.
So b will be destoryed firstly at the end of main(), a will be destroyed after that.
For the initialization,
are initialized the first time control passes through their declaration
So b will be initialized firstly in main(), then a gets initialized.
Because they have different lifespans. A is declared as function-local static variable.
Object created by declaration of automatic function-local variable got lifespan which begins before any use of that object and ends with the most nested code block (braces block) containing that declaration. In your case that's function main() body.
Object created by declaration of static function-local variable begins to exist after execution flow had entered the most nested code block containing that declaration and before any use of that object.
It got process-wide life span (stops to exist at std::atexit()), which happens after the function main() will be exited.
SO they are created in this particular case in order of declaration, but A will get destroyed way later. If your function was called twice, you'd see that B would be created twice but A only once. If function's flow would somehow omit either declaration, by if() statement or by returning early, the order of their creation of would change or both may be omitted.
It's implementation specific detail, but usually destruction of function-local statics implemented in same way as destruction of global objects, by call to a library function that lies under implementation of std::atexit, adding the address of destructor bound with value of pointer to object itself, but the execution may be concurrent (or may be not) with result of user's calls of std::atexit.
As addition to already existing answers, lets take a more phenomenological approach. Consider a small change on your example:
void foo() {
B b;
static A a;
}
int main() {
foo();
foo();
}
I assume you know that a is initialized only once and on the second call we get the exact same object a, because it is declared as static. Hence, it cannot be destroyed during or directly after the first call to foo. The expected first part of the output is
B::B // first call to foo()
A::A
B::~
B::B // second call to foo()
// no second call to A::A !
B::~
a can only be destroyed when your program terminates, otherwise you could not "reuse" it when calling the function again (thats why I had to modify the example, you cannot call main). As other answers explain in great detail, this happens after main returns. Hence last line of output will be
A::~
I have this code:-
int i;
class A
{
public:
~A()
{
i = 10;
}
};
int& foo()
{
i = 3;
A ob;
return i;
}
int main()
{
cout << "i = " << foo() << endl; //call to foo
return 0;
}
I'm confused about the order in which the compiler executes this code after encountering the return i statement.
My guess:
A variable of the caller(main) is made(say K) and a reference to it is passed to foo(), when the return statement is encountered, the compiler copies the value of the return statement into K, in this case the address of i, as a reference is being returned. Then it jumps to the end of foo() and the destructor for class object ob is called which changes the value of i to 10. This is followed by the removal of foo() and all its variables(including the reference to K passed to foo) from the call stack and the control is returned to main where K replaces the call to foo() and the cout is implemented.
Is this the correct order of actions taken by the compiler ?
I searched extensively for what happens in memory when a return is called and this was the best result, though it is for C#.
The function foo is in scope any place inside this source file, so there's no problem calling it.
As for the reference it's returning, i is a file scope variable and thus has static storage duration, which means its lifetime is the life of the program. This means you're allowed to return a reference to it from foo.
Had you attempted to return a reference to a local variable like this:
int& foo()
{
int x = 3;
return x;
}
That would invokes undefined behavior since the variable no longer exists after the function exits.
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
when the above program is run,the output is 30.The integer variable x was returned,as a reference to the main() function and it is assigned the value of 30.But isn't the scope of x limited to the fun() function?;If so,why are we able to change the value of it in main function??
Scope is limited means any attempt to access x directly outside the scope is forbidden.
Within a scope, unqualified name lookup can be used to associate the
name with its declaration.
But you can always return a pointer or reference to this variable if variable is alive and you change it through that reference or pointer which points to the same variable. The name of this reference may be anonymous (temporary) or may be bound to some named reference.
About lifetime, it starts when the function containing static variable is called first time and ends when the program end.
Indeed the scope of x is limited to fun().
But because that function returns a reference to x, the caller (i.e. main) is able to modify x through that reference. That's what's happening here: x is set to 10 the first time the function is entered, but is changed to 30 by the assignment fun() = 30.
I'm quite confident that globally declared variables get allocated (and initialized, if applicable) at program start time.
int globalgarbage;
unsigned int anumber = 42;
But what about static ones defined within a function?
void doSomething()
{
static bool globalish = true;
// ...
}
When is the space for globalish allocated? I'm guessing when the program starts. But does it get initialized then too? Or is it initialized when doSomething() is first called?
I was curious about this so I wrote the following test program and compiled it with g++ version 4.1.2.
include <iostream>
#include <string>
using namespace std;
class test
{
public:
test(const char *name)
: _name(name)
{
cout << _name << " created" << endl;
}
~test()
{
cout << _name << " destroyed" << endl;
}
string _name;
};
test t("global variable");
void f()
{
static test t("static variable");
test t2("Local variable");
cout << "Function executed" << endl;
}
int main()
{
test t("local to main");
cout << "Program start" << endl;
f();
cout << "Program end" << endl;
return 0;
}
The results were not what I expected. The constructor for the static object was not called until the first time the function was called. Here is the output:
global variable created
local to main created
Program start
static variable created
Local variable created
Function executed
Local variable destroyed
Program end
local to main destroyed
static variable destroyed
global variable destroyed
Some relevant verbiage from C++ Standard:
3.6.2 Initialization of non-local objects [basic.start.init]
1
The storage for objects with static storage
duration (basic.stc.static) shall be zero-initialized (dcl.init)
before any other initialization takes place. Objects of
POD types (basic.types) with static storage duration
initialized with constant expressions (expr.const) shall be
initialized before any dynamic initialization takes place.
Objects of namespace scope with static storage duration defined in
the same translation unit and dynamically initialized shall be
initialized in the order in which their definition appears in
the translation unit. [Note: dcl.init.aggr describes the
order in which aggregate members are initialized. The
initialization of local static objects is described in stmt.dcl. ]
[more text below adding more liberties for compiler writers]
6.7 Declaration statement [stmt.dcl]
...
4
The zero-initialization (dcl.init) of all local objects with
static storage duration (basic.stc.static) is performed before
any other initialization takes place. A local object of
POD type (basic.types) with static storage duration
initialized with constant-expressions is initialized before its
block is first entered. An implementation is permitted to perform
early initialization of other local objects with static storage
duration under the same conditions that an implementation is
permitted to statically initialize an object with static storage
duration in namespace scope (basic.start.init). Otherwise such
an object is initialized the first time control passes through its
declaration; such an object is considered initialized upon the
completion of its initialization. If the initialization exits by
throwing an exception, the initialization is not complete, so it will
be tried again the next time control enters the declaration. If control re-enters the declaration (recursively) while the object is being
initialized, the behavior is undefined. [Example:
int foo(int i)
{
static int s = foo(2*i); // recursive call - undefined
return i+1;
}
--end example]
5
The destructor for a local object with static storage duration will
be executed if and only if the variable was constructed.
[Note: basic.start.term describes the order in which local
objects with static storage duration are destroyed. ]
The memory for all static variables is allocated at program load. But local static variables are created and initialized the first time they are used, not at program start up. There's some good reading about that, and statics in general, here. In general I think some of these issues depend on the implementation, especially if you want to know where in memory this stuff will be located.
The compiler will allocate static variable(s) defined in a function foo at program load, however the compiler will also add some additional instructions (machine code) to your function foo so that the first time it is invoked this additional code will initialize the static variable (e.g. invoking the constructor, if applicable).
#Adam: This behind the scenes injection of code by the compiler is the reason for the result you saw.
I try to test again code from Adam Pierce and added two more cases: static variable in class and POD type. My compiler is g++ 4.8.1, in Windows OS(MinGW-32).
Result is static variable in class is treated same with global variable. Its constructor will be called before enter main function.
Conclusion (for g++, Windows environment):
Global variable and static member in class: constructor is called before enter main function (1).
Local static variable: constructor is only called when execution reaches its declaration at first time.
If Local static variable is POD type, then it is also initialized before enter main function (1).
Example for POD type: static int number = 10;
(1): The correct state should be: "before any function from the same translation unit is called". However, for simple, as in example below, then it is main function.
#include <iostream>
#include <string>
using namespace std;
class test
{
public:
test(const char *name)
: _name(name)
{
cout << _name << " created" << endl;
}
~test()
{
cout << _name << " destroyed" << endl;
}
string _name;
static test t; // static member
};
test test::t("static in class");
test t("global variable");
void f()
{
static test t("static variable");
static int num = 10 ; // POD type, init before enter main function
test t2("Local variable");
cout << "Function executed" << endl;
}
int main()
{
test t("local to main");
cout << "Program start" << endl;
f();
cout << "Program end" << endl;
return 0;
}
result:
static in class created
global variable created
local to main created
Program start
static variable created
Local variable created
Function executed
Local variable destroyed
Program end
local to main destroyed
static variable destroyed
global variable destroyed
static in class destroyed
Anybody tested in Linux env ?
Or is it initialized when doSomething() is first called?
Yes, it is. This, among other things, lets you initialize globally-accessed data structures when it is appropriate, for example inside try/catch blocks. E.g. instead of
int foo = init(); // bad if init() throws something
int main() {
try {
...
}
catch(...){
...
}
}
you can write
int& foo() {
static int myfoo = init();
return myfoo;
}
and use it inside the try/catch block. On the first call, the variable will be initialized. Then, on the first and next calls, its value will be returned (by reference).
Static variables are allocated inside a code segment -- they are part of the executable image, and so are mapped in already initialized.
Static variables within function scope are treated the same, the scoping is purely a language level construct.
For this reason you are guaranteed that a static variable will be initialized to 0 (unless you specify something else) rather than an undefined value.
There are some other facets to initialization you can take advantage off -- for example shared segments allow different instances of your executable running at once to access the same static variables.
In C++ (globally scoped) static objects have their constructors called as part of the program start up, under the control of the C runtime library. Under Visual C++ at least the order that objects are initialized in can be controlled by the init_seg pragma.
In the following code it prints Initial = 4 which is the value of static_x as it is implemented in the compiling time.
int func(int x)
{
static int static_x = 4;
static_x = x;
printf ("Address = 0x%x",&static_x ); // prints 0x40a010
return static_x;
}
int main()
{
int x = 8;
uint32_t *ptr = (uint32_t *)(0x40a010); // static_x location
printf ("Initial = %d\n",*ptr);
func(x);
return 0;
}