Questions on Destructor

1. Why is the destructor called before going out of scope?

2. Why is the statically allocated object able to print after being destroyed?

See output.
Inside the 2-argument constructor
Inside the 2-argument constructor
Inside the destructor: realPart = 10 complexPart = 15
Printing out statically allocated object
real = 10 complex = 15
Printing out dynamically allocated object
real = 15 complex = 10
Inside the destructor: realPart = 15 complexPart = 10
Okey-dokey! All done!
Press any key to continue . . .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>

using namespace std;

class ComplexNumber
{
private:
  float realPart;
  float complexPart;
public:
  ComplexNumber() : realPart(0.0),complexPart(0.0)
  {
    cout << "No arg-constructor called" << endl;
  }    
  ComplexNumber(float c, float r) : realPart(r) , complexPart(c)
  {
    cout << "Inside the 2-argument constructor" << endl;  
  }

  ComplexNumber(const ComplexNumber& rhs) : 
     realPart(rhs.realPart), complexPart(rhs.complexPart)
  {
    cout << "Inside the copy constructor" << endl;  
  }

  ~ComplexNumber()
  {
    cout << "Inside the destructor: realPart = " << realPart <<" complexPart = " << complexPart << endl; 
  }

  void setRealPart(float r)
  {
    realPart = r;
  }

  void setComplexPart(float c)
  {
    complexPart = c;
  }

  float getRealPart()
  {
    return realPart;
  }

  float getComplexPart()
  {
    return complexPart;
  }

  void print()
  {
    cout<<"real = " << realPart << " complex = " << complexPart << endl;
  }
};

int main()
{
 	{
		ComplexNumber* cDynamic = new ComplexNumber(10, 15);
		ComplexNumber* cStatic = &ComplexNumber(15, 10);

		cout << "Printing out statically allocated object" << endl;
		cStatic->print();
		cout << "Printing out dynamically allocated object" << endl;
		cDynamic->print();

		delete cDynamic;
		cout << "Okey-dokey! All done!" << endl;
	}

  system("pause");
  return 0;
}
1. You do create an unnamed temporary object on line 61 and initialize a local pointer variable with the address of the temporary. The lifetime of a temporary is (usually) only the duration of the statement. The temporary dies on line 61 too.

A compiler does not allow that:
 In function 'int main()':
61:49: error: taking address of temporary [-fpermissive]

Your compiler is sloppy.


2. You do read "values" from unallocated memory. That is undefined behaviour.
keskiverto,

The compiler I am using is free.

Anyway, I revised line 61 into two lines.
1
2
ComplexNumber cS{15, 10};
ComplexNumber* cStatic = &cS;



I ran the program with this change and got this output.

Inside the 2-argument constructor
Inside the 2-argument constructor
Printing out statically allocated object
real = 10 complex = 15
Printing out dynamically allocated object
real = 15 complex = 10
Inside the destructor: realPart = 15 complexPart = 10
Okey-dokey! All done!
Inside the destructor: realPart = 10 complexPart = 15
Press any key to continue . . .


1. Why is the output for the statically allocated object reversed? i.e., the real part is equal to the complex part, and the complex part is equal to the real part.

2. Similarly, why did the output for the dynamically allocated object come out reversed?

1.

There is a bit of confusion in the constructor and lines 60, 61.

Does this make more sense?

1
2
3
4
ComplexNumber(float c, float r) : complexPart(c) , realPart(r) 
  {
    cout << "Inside the 2-argument constructor" << endl;  
  }


1
2
3
4
5
6
7
8
	
		ComplexNumber* cStatic = &ComplexNumber(15.0, 10.0); // swapped these two lines to match output
                ComplexNumber* cDynamic = new ComplexNumber(55.0, 77.0);  // different numbers here not reversed

		cout << "Printing out statically allocated object" << endl;
		cStatic->print();
		cout << "Printing out dynamically allocated object" << endl;
		cDynamic->print();


Not that it makes any difference to the compiler, just for humans :+)

Some of the member functions should be marked const

Consider using std::unique_ptr instead of new, relieve yourself of memory management , destructors etc. It works in the presence of exceptions.


You might find this video interesting:

https://www.youtube.com/watch?v=PNRju6_yn3o

Edit:

The compiler I am using is free.


Most compilers have plenty of options for warnings, turn on as many of them as is reasonable, they are your friend. For example with g++:

g++ -std=c++17 -Wall -Wextra -pedantic-errors *.cpp -o ExecutableName

Despite all that, these ones are handy too:
http://www.cplusplus.com/forum/general/183731/#msg899203

Not sure what the story is for VS on windows, I have heard that /w4 produces too many warnings, including many from system header files. Maybe you can find the equivalent of those mentioned above, in VS if you use it?
Last edited on
Thank you, TheIdeasMan. You found the bug.
Topic archived. No new replies allowed.