Q related to object container

P

Pranav

Can any one help me about how many times the Ctor and Dtor are getting
called in the following code? I am getting o/p but not getting it..,
Re cnt value___

class MyClass{
public :
static int cnt;
MyClass ( );
void disp( );
~MyClass( );
};

MyClass :: MyClass( ){
cnt++ ;
cout << "Ctor " << cnt << "___" ;
}

MyClass :: ~MyClass( ){
cnt-- ;
cout << "Dtor " << cnt << "___" ;
}

void MyClass :: disp( ){
cout << "\nDisplay Function " << cnt << endl;
}

int MyClass :: cnt = 0;

main()
{
stack< MyClass, vector<MyClass> > myStack;
int i;

for ( i=0; i<10; i++ )
myStack.push( MyClass() );

for ( i=0; i<5; i++ ) {
myStack.top.disp();
myStack.top.pop();
}

//Code Ends Here_____________
char asdf;
cin >> asdf;
return 0;
}
 
P

Pranav

Can any one help me about how many times the Ctor and Dtor are getting
called in the following code? I am getting o/p but not getting it..,
Re cnt value___

class MyClass{
public :
       static int cnt;
       MyClass ( );
       void disp( );
       ~MyClass( );

};

MyClass :: MyClass( ){
        cnt++ ;
        cout << "Ctor " << cnt << "___" ;

}

MyClass :: ~MyClass( ){
        cnt-- ;
        cout << "Dtor " << cnt << "___" ;

}

void MyClass :: disp( ){
        cout << "\nDisplay Function " << cnt << endl;

}

int MyClass :: cnt = 0;

main()
{
      stack< MyClass, vector<MyClass> > myStack;
      int i;

      for ( i=0; i<10; i++ )
          myStack.push( MyClass() );

      for ( i=0; i<5; i++ )     {
           myStack.top.disp();
           myStack.top.pop();
       }

//Code Ends Here_____________
char asdf;
cin >> asdf;
return 0;



}

My type O Mistake in above code___
myStack.top().pop();

Please check o/p an tell me why the value of cnt -ve?
 
P

Pranav

for ( i=0; i<5; i++ ) {
myStack.top().disp();
myStack.pop();
}

Sorry for my typo mistakes_____
 
Z

ZikO

Pranav said:
Please check o/p an tell me why the value of cnt -ve?

In the line myStack.push(myClass()) there are 3 actions:
1) temporary object is created by constructor (cnt++ = 1)
2) temporary object is copied into stack
3) temporary object is removed from memory by destructor cnt--

So as you see. The destructor is run every time you copy object to the
stack due to the temporary object which is removed every time. So cnt is
always equal 0.

You have to have a copy constructor to fix it:

class MyClass {
// ...
MyClass::MyClass(const MyClass& mc);
};

// ...
MyClass::MyClass(const MyClass& mc) {
cnt = mc.cnt+1;
cout << "Copy Ctor " << cnt << "___" << endl;
}

Regards.


PS. This is code with the copy constructor.
#include <iostream>
#include <stack>
#include <vector>

using namespace std;

class MyClass {
public:
static int cnt;
MyClass();
void disp();
~MyClass();
MyClass(const MyClass& mc);
};

MyClass::MyClass(){
cnt++ ;
cout << "Ctor " << cnt << "___" << endl;
}

MyClass::~MyClass() {
cnt-- ;
cout << "Dtor " << cnt << "___" << endl;;
}

MyClass::MyClass(const MyClass& mc) {
cnt = mc.cnt+1;
cout << "Copy Ctor " << cnt << "___" << endl;
}

void MyClass::disp() {
cout << "\nDisplay Function " << cnt << endl;
}

int MyClass::cnt = 0;

int main() {
stack<MyClass> myStack;
int i;
for ( i=0; i<10; i++ ) {
myStack.push(MyClass());
}
for ( i=0; i<5; i++ ) {
myStack.top().disp();
// myStack.top.pop();
}

return 0;
}
 
P

Pranav

In the line myStack.push(myClass()) there are 3 actions:
1) temporary object is created by constructor (cnt++ = 1)
2) temporary object is copied into stack
3) temporary object is removed from memory by destructor cnt--

So as you see. The destructor is run every time you copy object to the
stack due to the temporary object which is removed every time. So cnt is
always equal 0.

You have to have a copy constructor to fix it:

class MyClass {
// ...
MyClass::MyClass(const MyClass& mc);

};

// ...
MyClass::MyClass(const MyClass& mc) {
        cnt = mc.cnt+1;
        cout << "Copy Ctor " << cnt << "___" << endl;

}

Regards.

PS. This is code with the copy constructor.
#include <iostream>
#include <stack>
#include <vector>

using namespace std;

class MyClass {
public:
        static int cnt;
        MyClass();
        void disp();
        ~MyClass();
        MyClass(const MyClass& mc);

};

MyClass::MyClass(){
        cnt++ ;
        cout << "Ctor " << cnt << "___" << endl;

}

MyClass::~MyClass() {
        cnt-- ;
        cout << "Dtor " << cnt << "___" << endl;;

}

MyClass::MyClass(const MyClass& mc) {
        cnt = mc.cnt+1;
        cout << "Copy Ctor " << cnt << "___" << endl;

}

void MyClass::disp() {
        cout << "\nDisplay Function " << cnt << endl;

}

int MyClass::cnt = 0;

int main() {
        stack<MyClass> myStack;
        int i;
        for ( i=0; i<10; i++ ) {
                myStack.push(MyClass());
        }
        for ( i=0; i<5; i++ )     {
                myStack.top().disp();
                // myStack.top.pop();
        }

        return 0;

}


Thank You ZikO___ For clearing things But one more query I have that
As many times the ctor is called why not the dtor is called to destroy
the objects ??
 
S

SG

Thank You ZikO___ For clearing things But one more query I have that
As many times the ctor is called why not the dtor is called to destroy
the objects ??

Can you rephrase that question?
What kind of behaviour do you observe?
What kind of behaviour do you expect?

In case you increment the counter in the copy constructor as well it
should tell you exactly how many objects of this class are currently
"alive". So, after putting 10 objects into the stack and popping 5
elements the counter "cnt" should be equal to 5.

But this counter doesn't tell you how many times a ctor and dtor was
called. It only tells you the difference between number of ctor calls
and dtor calls. The C++ language allows the compiler to optimize some
copies away which is why you might experience different number of
total calls on different compilers. In this case, however, there's no
situation where this kind of optimization is possible -- as far as I
can tell. So, I would expect to see
default-ctor: 10
copy-ctor: 10
dtors: 15 = 10 + 5 (10 temporaries and 5 copies you popped
from the stack)

(Warning: I didn't actually test it.)

Cheers!
SG
 
B

Bart van Ingen Schenau

Thank You ZikO___ For clearing things But one more query I have that
As many times the ctor is called why not the dtor is called to destroy
the objects ??

The destructor *will* be called for each object. The problem might be
that for the objects contained in the stack, the destructor will only
be called when the stack itself is destroyed and that happens when the
program ends.

As you had an input statement right at the end of the program
(presumably to keep the window open), it is very likely that the
output from those destructors was not seen by you before the window
closed.
Try opening a command-line window and run the program from there.

Bart v Ingen Schenau
 
Z

ZikO

Pranav said:
Thank You ZikO___ For clearing things But one more query I have that
As many times the ctor is called why not the dtor is called to destroy
the objects ??

I must say I'm a bit confused ... I am not quite sure what you are
asking for. I assume the no of ctors should be the same as dtors ...

The number of constructors calls must be the same as number of
destructors (it doesn't matter which constructor is called default, copy
etc.) Otherwise, there would be remaining objects in memory after the
program has ended.




The routine of your program is simple (without copy ctor - copy constr
created by compiler):

inside local main() scope:

ctor temp myClass, cnt++ => cnt = 1
copy ctor, temp myClass into stack, cnt = 1
no of objects in stack = 1, cnt = 1;

dtor temp myClass, cnt-- => cnt = 0

create temp myClass, cnt++ => cnt = 1
copy temp myClass to stack, copy of cnt = 1
no of objects in stack = 2, cnt = 1;

dtor temp myClass, cnt-- => cnt = 0

..... 10 times

create temp myClass, cnt++ => cnt = 1
copy temp myClass to stack, copy of cnt = 1
no of objects in stack = 10, cnt = 1

dtor temp myClass, cnt-- => cnt = 0

no of ctors calls = 20, no of dtors calls = 10

calling 5 times top() which simply refer to last object of the stack but
not removing it from the stack. cnt = 0

out of main main scope

calling all destructors of objects created in main()

dtor of myClass, cnt-- => cnt = -1
.... 10 times
dtor of myClass, cnt-- => cnt = -10

no of destructors calls = 10

in general:
no ctors (20) = no of dtors (10+10 = 20)




The routine of your program is simple (with copy ctor):

inside local main() scope:

ctor temp myClass, cnt++ => cnt = 1
copy ctor, temp myClass into stack, cnt = cnt + 1 = 2
no of objects in stack = 1, cnt = 2;

dtor temp myClass, cnt-- => cnt = 1

create temp myClass, cnt++ => cnt = 2
copy temp myClass to stack, copy of cnt = cnt + 1 = 3
no of objects in stack = 2, cnt = 3;

dtor temp myClass, cnt-- => cnt = 2

..... 10 times

create temp myClass, cnt++ => cnt = 10
copy temp myClass to stack, copy of cnt = cnt + 1 = 11
no of objects in stack = 10, cnt = 11

dtor temp myClass, cnt-- => cnt = 11

no of ctors calls = 20, no of dtors calls = 10

calling 5 times top() which simply refer to last object of the stack but
not removing it, cnt = 10

out of main main scope

calling all destructors of objects created in main()

dtor of myClass, cnt-- => cnt = 9
.... 10 times
dtor of myClass, cnt-- => cnt = 0

no of destructors calls = 10

in general:
no ctors (20) = no of dtors (10+10 = 20)



PS. By the way, i have made a little mistake in the code. Since your cnt
is static it'd be better if copy constructor was:

MyClass::MyClass(const MyClass& mc) {
cnt++; // only one cnt for all objects of myClass
cout << "Copy Ctor " << cnt << "___" << endl;
}
 
S

SG

But this counter doesn't tell you how many times a ctor and dtor was
called.  It only tells you the difference between number of ctor calls
and dtor calls.  The C++ language allows the compiler to optimize some
copies away which is why you might experience different number of
total calls on different compilers.  In this case, however, there's no
situation where this kind of optimization is possible -- as far as I
can tell.  So, I would expect to see
  default-ctor: 10
  copy-ctor:    10
  dtors:        15 = 10 + 5  (10 temporaries and 5 copies you popped
                              from the stack)

I forgot to count the copies the vector needs to make to grow
automatically. After inserting 10 elements I get the following
counts:

def_ctor: 10
cop_ctor: 25 <-- depends on vector implementation
destruct: 25 <-- depends on vector implementation

The number of copies can be explained by the number of stars:

* 1 +
** 2 +
**** 4 +
******** 8 +
********** 10 = 25

So, in my case the std::vector implementation makes room for exactly
one element first. Then, each time the capacity is reached and another
element needs to be added a new array is allocated with twice the
size, the old elements are copied, the old array is destructed, and a
new element is added.


Cheers!
SG
 
P

Pranav

Ctor 1___
Dtor 0___
Ctor 1___
Dtor 0___
Dtor -1___
Ctor 0___
Dtor -1___
Dtor -2___
Dtor -3___
Ctor -2___
Dtor -3___
Ctor -2___
Dtor -3___
Dtor -4___
Dtor -5___
Dtor -6___
Dtor -7___
Ctor -6___
Dtor -7___
Ctor -6___
Dtor -7___
Ctor -6___
Dtor -7___
Ctor -6___
Dtor -7___
Dtor -8___
Dtor -9___
Dtor -10___
Dtor -11___
Dtor -12___
Dtor -13___
Dtor -14___
Dtor -15___
Ctor -14___
Dtor -15___

Display Function -15
Dtor -16___

Display Function -16
Dtor -17___

Display Function -17
Dtor -18___

Display Function -18
Dtor -19___

Display Function -19
Dtor -20___
Dtor -21___
Dtor -22___
Dtor -23___
Dtor -24___
Dtor -25___

This is what I was getting as Output__ My Question is If a constructor
is called to create an object then there is a destructor associated
with it__ Why there are more calls to Dtors then the Ctors?? The above
o/p is coming for the original code without copy constructor__
 
S

SG

This is what I was getting as Output__ My Question is If a constructor
is called to create an object then there is a destructor associated
with it__ Why there are more calls to Dtors then the Ctors??

There are not.
The above
o/p is coming for the original code without copy constructor__

That's your explanation right there. You don't count copy
constructions. If you don't supply a copy constructor the compiler
will generate a copy constructor for you. The compiler-generated copy-
constructor won't modify your counter.

Cheers!
SG
 
P

Pranav

There are not.


That's your explanation right there.  You don't count copy
constructions.  If you don't supply a copy constructor the compiler
will generate a copy constructor for you.  The compiler-generated copy-
constructor won't modify your counter.

Cheers!
SG

K__ Thank you SG.., Now my doubts are clear___ and it is always better
to have a copy constructor___
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,241
Latest member
Lisa1997

Latest Threads

Top