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.
Related
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::~
EDITED: Let's say we don't call explicitely the destructor of a heap-based object (delete A). If the pointer that points to "A" goes out-of-scope, is there a way the dynamic object remain accessible? for e.g., in the following code, can "a" be still alive after if-closing }?
class A{
void itsmethod();
};
int main()
{
if (true){
A* a = new A;
}
//...here how can I use dynamically allocated object?
a->itsmethod();
}
EDIT: As it was responded, the simplest immediate way is defining the pointer outside of if statement, but I am just wondering if there is any other option to prolong lifetime of dynamic object? Accordingly what else "A" class should provide? For instance passing by reference? Or equipping the class with move constructor... These suggestions may be irrelevant, I would like to hear your feedback.
I wonder if the object "a" is still alive after if-closing }?
The object a, which is a pointer, is not alive after the closing } of the if statement. The object to which a points to is in memory but it is not accessible with the posted code.
To be able to access the object to which a points to, declare a before the if statement.
int main()
{
A* a = nullptr;
if (true)
{
a = new A;
}
if ( a != nullptr )
{
a->itsmethod();
}
}
No and Yes: yes because dynamic memory is not freed up automatically. No because the code doesn't compile because a is scoped to if block and you are trying to use it from outside.
class A{
public:
int x;
};
int main(){
A* ptrA = NULL;
if(true){
// Everything declared here is accessible only here whatever being dynamic or static.
ptrA = new A;
ptrA->x = 10;
int x;
}
if(ptrA){
std::cout << ptrA->x << std::endl; // 10
delete ptrA;
}
return 0;
}
You must free up memory always when you're done with it otherwise it is a memory leak.
Above x is declared inside the if block on the stack so when end of if block is reached x will be destructed.
The object created by the new expression (i.e. by new A) will continue to exist.
The pointer a itself, since it has passed out of scope, will cease to exist as far as your program is concerned.
The net effect is that the dynamically allocated object is "leaked". It continues to exist after the block but there is no pointer or reference to it.
If you do something like
int main()
{
A *b;
if (true)
{
A* a = new A;
b = a;
}
a->itsmethod(); // diagnosible error
b->itsmethod(); // will work correctly
delete b; // destroy dynamically allocated object
b->itsmethod(); // undefined behaviour
}
then a->itsmethod() will give a compiler diagnostic (since a no longer exists) but the first b->itsmethod() will use the object created by the new expression. The second b->itsmethod() will compile, but yield undefined behaviour, since it accesses an object that no longer exists (due to the preceding delete b).
This happens because the pointer b continues to exist and, within the enclosed block, is assigned the value from a. So it then contains the result of the new expression.
No. The object 'a' will not be accessible anymore since its scope belongs to the if statement. However, there still is a memory address containing that object. This is why its good to do 'garbage collection' in programming.
Let's consider this demonstrative program
#include <iostream>
struct A
{
const char *s;
std::ostream & operator ()( std::ostream &os = std::cout ) const
{
return os << s;
}
};
int main()
{
A *a1;
if ( true )
{
A *a2 = new A { "Hello, Sepideha" };
a1 = a2;
}
( *a1 )() << std::endl;
delete a1;
return 0;
}
Its output is
Hello, Sepideha
Here the object a1 that has the type A * has the outer-most block scope of the function main.
The object a2 has the block scope of the if statement. It is alive only within this block.
At the same time there is dynamically created unnamed object of the type A pointer to which is assigned to a2 and then to a1. This unnamed object will be alive until the operator delete for a pointer that points to the object will be called. That is its live-time does not depend on the block scope of the if statement.
Because the pointer a1 points to this unnamed object then the pointer can be used outside the if statement to access the unnamed object in the dynamic memory.
After the statement with the delete operator this unnamed object stops to exist. But the object a1 is still alive.
Consider below code:
#include <iostream>
#include <stdexcept>
using namespace std;
int i;
class A{
public:
~A(){i=10;}
};
int func1()
{
i=3;
A Ob; // -> here local object , hence created and destroyed
return i;
}
int& func2()
{
i=8;
A obj;
return i;
}
int func3()
{
i=8;
{A obj;}
return i;
}
int main()
{
cout << "i : " <<func1() << endl;
cout << "i : " <<func2() << endl;
cout << "i : " <<func3() << endl;
return(0);
}
OutPut:
$ ./TestCPP
i : 3
i : 10
i : 10
Can someone explain why first i is 3 ? In func1() , A Ob is local variable and hence it is created and destroyed. When it is destroyed, it will call its destructor modifying i to 10 and I am expecting i to be 10, but answer shows i : 3.
Stack objects are still in scope when you call return, so the value of i is still 3 because the destructor for A has not yet been called. The stack objects are removed when the function's stack unwinds, which is after the return value has been set.
Imagine if this weren't the case, if stack objects could be destroyed during the return. How would you be able to return a local value from the function?
Response to comments
#paddy Can u explain func2 and func3 in that case ?
On the surface, func2 looks almost exactly the same as func1, and you would be forgiven for thinking it should return 8. But the difference here is that it returns int& instead of int. That means a reference to i is returned by return i;. Even though i is 8 when the stack starts unwinding, by the time obj is destroyed and the return value is popped back to the caller, the value of i is 10. Because we returned a reference, the return value is dereferenced and the current value of i (10) is used.
For func3 it's even easier. This returns a normal int, just like func1. But the instance A obj; is inside its own block scope: { A obj; }. So it is destroyed before the return, and the value of i is 10 when we return from the function.
From the Standard (C++11, 3.7.3):
(1) Block-scope variables explicitly declared register or not explicitly declared static or extern have automatic storage duration. The storage for these entities lasts until the block in which they are created exits.
[...]
(3) If a variable with automatic storage duration has initialization or a destructor with side effects, it shall not
be destroyed before the end of its block, nor shall it be eliminated as an optimization even if it appears to
be unused, except that a class object or its copy/move may be eliminated as specified in 12.8.
What this means is that the lifetime of A ends whereever the block in which it is declared ends. In the case of func1, this is after the return-statement. In the case of func3 it is before the return-statement.
(A "block" is a piece of code enclosed in curly braces: {...}.)
Hence, func1 evaluates the return value before the destructor of A is called and therefore returns 3. func3 evaluates the return value after the destructor is called and therefore returns 10.
In the case of func2, the order is the same as in func1, but because it returns a reference, the value modification performed by the destructor of A, even though it is performed after the evaluation of the return value, has an effect on the value that was returned.
It has to do with whether you are returning a copy of i or a reference to it before the A destructor is called:
func1() case:
i is set to 3
the value of i is returned as a copy of i (as a temporary)
i is set to 10 in A destructor
the copy of i (3) is printed
func2() case:
i is set to 8
the value of i is returned as reference to the global variable i
i is set to 10 in A destructor
the current value of i is printed
func3() case:
i is set to 8
i is set to 10 in A destructor
the value of i is returned as a copy
the copy of i (10) is printed
The destructor occurs after the return statement but before the next line of the calling function. The return value is saved in a hidden variable, then the destructors and other function cleanup is called (such as returning the stack), then execution continues in the caller.
To further clarify- imagine the return line was return i+A.foo();. You wouldn't want to call the destructor until after this line, or A wouldn't be valid to call foo on. This is why destructors are always called after the return.
The variable "i" is global throughout the entire of your code, there is no "local" instance of it.
Objects are destroyed when they go out of scope, which is after the "return" in your functions, not before it. So the first dtor is called only after the first value of i has been returned and the function has ended.
i = 3; <-- sets i to 3
A Ob; <-- constructs object.
return i; <-- places the value "3" in the return value register.
} <-- destroys object changing future values of "i" to 10.
If you wanted to return "i" rather than the value it contains at the time of the expression "return i" you would have to make the following change:
int& func1()
{
i = 3; <-- sets i to 3
A Ob; <-- constructs object.
return i; <-- places a reference to "i" in the return value register.
} <-- destroys object changing the value of "i" to 10
See http://ideone.com/XXYu2u
I strongly encourage you to walk thru this program before and after with a debugger to better familiarize yourself with the entire process - it's the best way to solidify your understanding of what's going on.
When I capture an object by reference in a C++11 lambda, let the object go out of scope, and then execute the lambda, it still has access to the object. When I execute the following code, the lambda call can still access the object, although the destructor has already been called! Can someone explain why this works and why I don't get a runtime error?
#include <iostream>
class MyClass {
public:
int health = 5;
MyClass() {std::cout << "MyClass created!\n";}
~MyClass() {std::cout << "MyClass destroyed!\n";}
};
int main(int argc, const char * argv[])
{
std::function<bool (int)> checkHealth;
if(true) {
MyClass myVanishingObject;
checkHealth = [&myVanishingObject] (int minimumHealth) -> bool {
std::cout << myVanishingObject.health << std::endl;
return myVanishingObject.health >= minimumHealth;
};
} // myVanishingObject goes out of scope
// let's do something with the callback to test if myVanishingObject still exists.
if(checkHealth(4)) {
std::cout << "has enough health\n";
} else {
std::cout << "doesn't have enough health\n";
}
return 0;
}
Here's the output:
MyClass created!
MyClass destroyed!
5
has enough health
According to the cppreference.com website's documentation of lambda functions
Dangling references
If an entity is captured by reference, implicitly or explicitly, and the function call operator of the closure object is invoked after the entity's lifetime has ended, undefined behavior occurs. The C++ closures do not extend the lifetimes of the captured references.
In other words, the fact that you have captured the object by reference and then let the object's lifetime ends means that invoking the lambda causes undefined behavior. Since one possible way that UB might work is "the object appears to be alive and well even though the object is dead," I suspect that you are seeing undefined behavior manifesting itself as nothing appearing to have gone wrong.
I suspect this would be the case if the compiler allocated a unique stack location to the temporary variable. This would mean that after the lifetime of the object ends, before main returns, the memory wouldn't be touched by anything. Accordingly, you'd see the variable holding the value 5 just as before, since nothing else is writing on top of it.
Hope this helps!
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