I have this Instance of class A, which i first assign, then assign again, but the compiler calls the destructor AFTER they class has been constructed the second time, why?

class A{
    public:
    int *Int;
    A(int b) { Int = new int(b); cout << "CONSTRUCTOR " <<endl; };
    ~A()  { delete[] Int; cout << "DESTRUCTOR" << endl; }
};

int main(){
     A Inst(3);
    Inst = A(4);
    cout << *Inst.Int << endl;
}

output:

CONSTRUCTOR
CONSTRUCTOR
DESTRUCTOR
0

the int should be 3, but since the class was destroyed, it is 0.
To me, a more logic behaviour would be that the compiler destructs the object BEFORE creating a new.

Is the only solution creating a member-function that changes the variable?
like
void ChangeInt(int b) { delete[] b; Int= new int(b); }
It seems a bit unecessary, since i already have a constructor that does exactly the same thing, but the destructor messes it all up.
Why?

Recommended Answers

All 12 Replies

what does Inst = A(4); do?

Member Avatar for jencas

Where are copy constructor and assignment operator?

You are actually doing crime here but letting the compiler generate the copy constructor and the assignment operator,
Look closely what Inst = A(4); do(sorry Comatose, I am answering that):
On the right side of the assignment operator, a temporary object is created, a copy constructor is called which copy the value of all the member of that temporary object to Inst and then, listen up, call the destructor of that temporary object.
Now as the destructor deletes the memory assigned to Int, the value of *Int is shown as zero(actually it is undefined). Now again as you program terminates, the destructor of Inst is called, which tries to delete a pointer which is already passed to delete once. And so, your program gets screwed up( the second delete, actually throws an exception, which is un-catched)

.

commented: Precisely. :) +11

Thanks for the reply, siddhant3s.

Even if I cange it like this

Inst = 4;

The same result is produced. I see the problem, Inst is assigned to a temporary variable. So, how do I change Inst the "correct" way?

Yes, it will be the same output. Can you guess why?
This is called Implicit type conversion. In this case the statement Inst = 4; is equivalent to Inst=(A)4; which is doing the same thing.

So, how do I change Inst the "correct" way?

You should define your own copy-constructor, your own assignment operator to eradicate the problem completely.

I understand, but why does that temporary variable only call the destructor, and not the constructor? It needs to be created AND destroyed, right?

It is calling the Constructor too!
That's why you are getting output as two Constructor's and one Constructors..

CONSTRUCTOR //this is from A Inst(3);
CONSTRUCTOR // Inst = A(4);
DESTRUCTOR//from Inst = A(4);
0

Ok thanks, but is it even to use the constructor function (not the copy constructor) again AFTER an object already has been constructed.
Because, if I use the copy constructor or assignment the object needs to be constructed twice, first as a local variable, then copied into the object itself. Is'nt that a bit inefficient?

I meant, " is it even POSSIBLE to use"...

Lets say if I issue the following statement:

A Inst(4);//Constructor of Inst called with parameter 4
Inst=A(3);//Constructor of temp object(not Inst) called with parameter 3. Also
                 //the assignment operator of Inst called with temp object
                 //as parameter

So, clearly the two Constructor calls which you see as your output are from different object. The first one is from Inst and second one from the temp object.
The one Destructor call is coming from the temp object.

Because, if I use the copy constructor or assignment the object needs to be constructed twice

No. the popular definition of copy-constructor is :

class myType
{
private:
int a;
public:
mType(myType& copyFrom) //this is copy constructor
{
a=copyFrom.a;//copying
}
};

As you can see the value is passed by reference. Hence there will not be any copy of the copyFrom object.

Now, for your problem, the most probable copy constructor and assignment operator will look as below:

#include<iostream>
using std::cout;
using std::endl;
class A
{
public:
    int *Int;
    A()    {Int = new int;}
    A(int b)
    {
        Int = new int(b);
        cout << "one-argument CONSTRUCTOR " <<endl;
    }
    A(const A &copyFrom)
    {
        Int = new int;
        *Int=*copyFrom.Int;
        cout<<"Calling Copy Constructor"<<endl;

    }
    A& operator = (const A & copyFrom)
    {
        *Int=*copyFrom.Int;
        cout<<"Calling Assignment Operator"<<endl;
        return *this;
    }

    ~A()
    {
        delete Int;
        cout << "DESTRUCTOR" << endl;
    }
};

int main()
{
    A Inst(1);
    Inst=A(5);
    cout << *Inst.Int << endl;

    A Binst=Inst;

    cout << *Inst.Int << endl;
}

Output:

one-argument CONSTRUCTOR //Due to Line 37
one-argument CONSTRUCTOR // Due to  Line 38(the temp object)
Calling Assignment Operator  //Due to  Line 38(overloaded = operator)
DESTRUCTOR  //Due to  Line 38(the temp object)
5 // Due to  Line 39
Calling Copy Constructor // // Due to  Line 41
5 // Due to  Line 43
DESTRUCTOR // Due to  Termination of Program (Binst)
DESTRUCTOR // Due to  Termination of Program (Inst)

>the popular definition of copy-constructor is ... myType(myType&) It's a very bad (and dangerous) copy constructor signature, never use it. Don't invent wheel:

Class(const Class&); // That's all, folks!

>>the popular definition of copy-constructor is ... myType(myType&)
I just wanted to emphasize on call by reference thing. Sure this defination is bad without a const modifer. As you can see, I have used the const specifier in my code.
ArkM is right.
Let's see what good the const declaration do to us. Say, you have a copy constructor whose arguments are taken as const-and-by-reference

Class(const Class& copyFrom)
{

//do something to copy
copyFrom=3;//error copyFrom is const, it cannot change
}

As commented above, the compiler causes a error at compile time.
Often such assignments are typographical errors.
Thus, you are saved by scratching your head at the run-time.
As a rule of thumb, it is always good to catch error in compile time itself.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.