So I have some C++ code:
#include <iostream>
using namespace std;
class C {
public:
C() {i = 9; cout << "C0:" << i << endl;}
C(int i0) {i = i0; cout << "C1:" << i << endl;}
~C() {cout << "C2:" << i << endl;}
private:
int i;
};
void f(int i) {
C c(i);
}
int main(int argc, char* argv[]) {
for (int i = 0; i < 1; i++) {
cout << "X" << endl;
f(i);
cout << "Y" << endl;
}
}
And the output is:
X
C1:0
C2:0
Y
This is strange because the line C2:0 is part of the destructor which I've learned is called after the last statement. So my question is in what kind of situations are destructors called before the last statement?
Object C is created inside function f. So, C is destroyed when the f function scope ends, simply right after calling f(i) in main, f scope is destroyed, and the C object's destructor is called.
Automatic variables (your c in f()), are cleaned up when the stack they are on goes away.
So in this case, it's as your f(i) call is returning. For objects, this includes calling the destructor.
Globals and static variables are also cleaned up as your program exits, when it exits properly. If it exits via an uncaught exception, they may not be cleaned up (it's not required).
This is strange because the line C2:0 is part of the destructor which I've learned is called after the last statement.
The destructor is called after the last statement of the scope containing the variable which is an instance of a class.
C is created and destroyed within the scope of the f(int i) function so the destructor of C prints "C2:0". f finishes and only then Y is printed.
Related
Chapter 6.1.1 of the book C++ Primer says the following:
Each local static object is initialized before the first time execution passes through the object’s definition. Local statics are not destroyed when a function ends; they are destroyed when the program terminates.
To check this, I ran the following code:
#include <iostream>
using std::clog;
using std::endl;
struct Bar {
Bar() {
clog << "constructing Num object" << endl;
}
int i = 0,
j = 0;
~Bar() {
clog << "destructing Num object" << endl;
}
};
void foo() {
clog << "foo() started" << endl;
static Bar b;
return;
}
int main() {
if (true) {
clog << "if-statement started" << endl;
foo();
}
clog << "if-statement exited" << endl;
return 0;
}
At this point in the book I haven't covered structs and classes yet, but it is my understanding that the function Bar() logs a message to the standard output when it gets created, and that b gets default initialized. If that is the case, then why does the output show that the object is constructed / initialized when control reaches static Bar b;, and not before it reaches this statement?
Output:
if-statement started
foo() started
constructing Num object
if-statement exited
destructing Num object
When are local static objects created?
As your book says: "before the first time execution passes through the object’s definition".
More precisely, the standard's wording is:
Dynamic initialization of a block-scope variable with static storage duration or thread storage duration is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization.
I think you're getting too hung up on the word "before". 🙂
I ran the following code
#include <iostream>
using namespace std;
class Count
{
private:
int count;
public:
//Constructor
Count():count(0) { cout << "Constructor called" << endl; }
//Destructor
~Count() { cout << "Destructor called" << endl; }
//Display the value.
Count display()
{
cout << "The value of count is " << count << endl;
return *this;
}
};
int main()
{
Count C;
C.display();
}
Result :-
Constructor called
The value of count is 0
Destructor called
Destructor called
In the above case, the destructor is called twice, one for destruction of the "this" object and one for return from main.
Is my observation correct ??
Can anyone explain me also the temporary object created in this process like why it is created, if created??
You are returning a copy from display() method thus it needs to be destructed too. So, in your main you actually have 2 objects, one - implicitly.
The destructor is called twice because your display function returns a copy of the Count instance that it is called on. So that gets destroyed along with your C instance within main.
2 instances = 2 destructor calls.
If you specify and implement your function to return an instance of Count then it will do so. If you don't want this behaviour, then change the return type to void and don't return anything - then your code will contain just the one instance C.
Your code here
Count display() {
// ^^^^^
cout << "The value of count is " << count << endl;
return *this; // <<<<<<
}
creates an implicit copy of your instance that is returned and immediately destroyed, hence the second destructor call.
Yes correct.
Your function display() created a copy which made a second object.
if you return a reference you wouldn't get the copy.
Count& display() { return *this; }
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can you print anything in C++, before entering into the main function?
Is there any possibility to run any other instructions before int main() is invoked?
int main(){cout<<"a";}
and before that call in main() there is call for cout<<"b"; somewhere before. Maybe this #define thing can help.
You don't need a define. Just create a global object (in the same file) and its ctor (or anything else you use to initialize it, such as calling a function) will run before main is invoked.
Edit: likewise, those global objects will be destroyed after main exits, so their destructors will run at that time.
Global objects are constructed before main() runs. So you can define a class, put your code in its constructor, and then declare a global instance of that class:
class temp
{
public:
temp()
{
cout << "before main" << endl;
}
~temp()
{
cout << "after main" << endl;
}
};
temp t;
int main()
{
cout << "in main" << endl;
return 0;
}
Global variables are also initialized before main() runs. You can define a function that returns a value, then call that function and assign the value to a global variable in its declaration, like #jrok showed.
Some compilers also support a #pragma startup statement to execute a user-defined function at startup (and corresponding #pragma exit statement for shutdown):
void beforeMain()
{
cout << "before main" << endl;
}
#pragma startup beforeMain
void afterMain()
{
cout << "after main" << endl;
}
#pragma exit afterMain
int main()
{
cout << "in main" << endl;
return 0;
}
Static variables exist outside of the function, in terms of their memory at least (not scope), right? But one thing that always concerned me, is what happens when I call the function a second time. For instance:
f(){
static char buffer[256*256];
stuff(buffer);
}
When I call this function a second time, wouldn't it technically be declaring the variable 'buffer' a second time? Or does it work differently with static variables (as opposed to normal ones) once everything is compiled?
... I sometimes wish there was a chart or something of what a c++ compiler usually turns code into (minus optimizations) so I wouldn't have to bother you fine folks with little questions like this, aha. Thank you in advance!
edit: I know it works like this, I just want to know why though. It's probably something mind numbingly simple...
Static storage duration objects in function scope.
These objects are created on first use.
Then destroyed in reverse order of creation (with other static storage duration objects).
#include <iostream>
class X
{
public:
X(int x): m(x) {std::cout << "X: " << m << " created\n"; }
~X() {std::cout << "X: " << m << " destroyed\n";}
private:
int m;
};
static X x1(1);
int test()
{
std::cout << "Test: Start\n";
static X x3(3);
std::cout << "Test: Finished\n";
return 5;
}
int main()
{
std::cout << "Main: Start\n";
X x2(2);
test();
X x4(4);
std::cout << "Main: Finished\n";
}
Now Try it: (comments added). SSDO => Static Storage Duration object.
g++ X.cpp
./a.out
X: 1 created // SSDO file scope.
Main: Start
X: 2 created
Test: Start
X: 3 created // SSDO created on first use (Notice not destroyed)
Test: Finished
Test: Start // Notice not created here.
Test: Finished
X: 4 created
Main: Finished
X: 4 destroyed
X: 2 destroyed // Main now really finished. after destroying local variables.
X: 3 destroyed // Destroy SSDO in reverse order of creation. (3 - 1)
X: 1 destroyed
No, you static means that it is outside the scope of your function. It has the same effect as writing:
static char buffer[256*256];
f(){
stuff(buffer);
}
Except that the buffer is only visible in the scope of your function, and the code is more readable.
(NOTE: My example doesn't apply when char is not a primitive type - in that case, it is constructed the first time it is "declared").
In this context, static means that the variable has application lifetime. It is allocated before main() the function is entered, and deallocated after main() has returned. Also, its value is preserved between function calls. Think of it as a global variable that is only visible from inside that function.
The variable exists before and after you call the function...it's static.
This example might illustrate it:
#include <iostream>
using namespace std;
void test() {
static int i = 123;
if (i == 123) {
i = 321;
}
cout << i << endl;
}
int main(int arg, char **argv) {
test();
test();
return 0;
}
The output is:
321
321
So "i" is only initialized the first time it is encountered, so to speak. But actually it's allocated at compile time for that function. Afterwards, it's just in the scope of the function test() as a variable, but it is static so changing it changes it in all future calls to test() as well.
In this example, why is it ok to return a stack variable? When t() returns, why is it not returning garbage, since the stack pointer has been incremented?
#include << string >>
#include << vector >>
#include << iostream >>
using namespace std;
class X{
public:
X() { cout << "constructor" << endl; }
~X() { cout << "destructor" << endl; }
};
vector <X> t()
{
cout << "t() start" << endl;
vector<X> my_x;
int i = 0;
printf("t: %x %x %x\n", t, &my_x, &i);
my\_x.push\_back(X()); my\_x.push\_back(X()); my\_x.push\_back(X());
cout << "t() done" << endl;
return my_x;
}
int main()
{
cout << "main start" << endl;
vector <X> g = t();
printf("main: %x\n", &g);
return 0;
}
output:
./a.out
main start
t() start
t: 8048984 bfeb66d0 bfeb667c
constructor
destructor
constructor
destructor
destructor
constructor
destructor
destructor
destructor
t() done
main: bfeb66d0
destructor
destructor
destructor
Basically when you return the stack variable my_x you would be calling the copy constructor to create a new copy of the variable. This is not true, in this case, thanks to the all mighty compiler.
The compiler uses a trick known as return by value optimization by making the variable my_x really being constructed in the place of memory assigned for g on the main method. This is why you see the same address bfeb66d0 being printed. This avoids memory allocation and copy construction.
Sometimes this is not at all possible due to the complexity of the code and then the compiler resets to the default behavior, creating a copy of the object.
Because parameters are passed by value. A copy is made. So what is being returned is not the value on the stack, but a copy of it.
Well a copy is returned, the only construct you can not return a copy of it is a static array. So you can not say this...
int[] retArray()
{
int arr[101];
return arr;
}
The compiler is optimized to handle returning "stack variables" without calling the copy constructor. The only thing you need to know about is that that memory allocation is in scope of both the function that allocated it on the stack and the function that the object is returned to.
It does NOT call the copy constructor nor does it allocate it twice.
There may be some special cases and of course it depends on the compiler -- for example, primitives may be copied -- but in general, objects allocated on the stack, don't get copied when being returned.
Example:
struct Test {
};
Test getTest() {
Test t;
std::cout << &t << std::endl; // 0xbfeea75f
return t;
}
int main(int argc, char *argv[])
{
Test t = getTest();
std::cout << &t << std::endl; // also 0xbfeea75f
}