• Advertisement
Sign in to follow this  

deconstructor called after constructor

This topic is 3578 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hello, i want to reuse a variable for another instance

myClass foo = myClass();

// some code here

foo = myClass();

// some other code here


the problem is, that it seems as if in the second line the constructor is called first, and then the destructor is automatically called on the new instance. i expected it to call the destructor first on the old instance and then call the constructor on the new instance. why exactly is the destructor called on the second instance here? thanks.

Share this post


Link to post
Share on other sites
Advertisement
The second line creates a temporary object and then uses the assignment operator on the first object to copy the state of the temporary to the original.

Share this post


Link to post
Share on other sites
Because once it gets assigned to the old object there's no reason to keep it around anymore.

Share this post


Link to post
Share on other sites
thank you,

but the way i understand it, there is no reason to keep the OLD object (the one that was created in the first line) around anymore. because the new object is now stored in foo, it should be kept around.

Share this post


Link to post
Share on other sites
Let's try explaining it this way, when you do this:

int i = 5;
i = 4;

i isn't destroyed. It gets a new value, but it's the same variable. The same thing happens with with class type. If you have

Foo f;
f = myClass();

f isn't destroyed. It just gets a new value which is equal to that of a default constructed myClass. The default constructed myClass temporary lives just long enough to pass its value on to f.

Share this post


Link to post
Share on other sites
Quote:
Original post by ehmdjii
thank you,

but the way i understand it, there is no reason to keep the OLD object (the one that was created in the first line) around anymore. because the new object is now stored in foo, it should be kept around.
New object yes, temporary, no.


// This:
myClass foo = myClass();

// Is the same as:
myClass tmp;
myClass foo(tmp); // I think, not 100% sure; might just use operator= rather than copy constructor
// destroy tmp here, it's no longer needed


After that, foo contains whatever tmp contained, and tmp doesn't need kept around any more.

Likewise:

// This:
foo = myClass();

// Is the same as:
myClass tmp2;
foo = tmp2;
// Destroy tmp2 here

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
myClass foo(tmp); // I think, not 100% sure; might just use operator= rather than copy constructor
// destroy tmp here, it's no longer needed
Sometimes the copy-constructor is called instead of the assignment operator, but never the other way around.
Both examples call the copy-constructor.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
Quote:
Original post by Evil Steve
myClass foo(tmp); // I think, not 100% sure; might just use operator= rather than copy constructor
// destroy tmp here, it's no longer needed
Sometimes the copy-constructor is called instead of the assignment operator, but never the other way around.
Both examples call the copy-constructor.

The copy constructor is never called instead of the assignment operator. If you're assigning to an existing object, calling the copy constructor instead would double construct an object. If you're "assingning" to an non-constructed object, the assignment operator wouldn't be called in the first place.

Share this post


Link to post
Share on other sites
ok thank you everybody.

so you are saying that the NEW object's contents are copied over to the OLD object. which means that only the values in the OLD object change, but the object stays the same.

the reason why i am actually posting this questions is because in the constructor some array is allocated which is deleted in the destructor. and if i call a function that accesses this array, the program crashes, because the array seems to got deleted.



myClass foo = myClass();
foo.operateOnArray(); // works

foo = myClass();
foo.operateOnArray(); // <- crash because the destructor has deleted the array?




Share this post


Link to post
Share on other sites
That probably means that you didn't write your assignment operator correctly.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
That probably means that you didn't write your assignment operator correctly.


actually i didnt write an assignment operator at all. do i have to?

Share this post


Link to post
Share on other sites
If in doubt, print out the function being called, and the address of the this pointer (And the other object pointer if it exists) for the following functions:
Default constructor
Copy Constructor
Destructor
Assignment operator

Also, make sure your copy constructor and assignment operator take one argument, a const reference to another object, and that your assignment operator returns *this at the end of it.

Share this post


Link to post
Share on other sites
If you write a copy constructor, assignment operator or destructor it probably means that you need to write all of them. This is called the rule of three.

Alternately you can switch from manually managing memory to something like a std::vector.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
If in doubt, print out the function being called, and the address of the this pointer (And the other object pointer if it exists) for the following functions:
Default constructor
Copy Constructor
Destructor
Assignment operator

Also, make sure your copy constructor and assignment operator take one argument, a const reference to another object, and that your assignment operator returns *this at the end of it.


EDIT:
Quote:
Original post by ehmdjii
actually i didnt write an assignment operator at all. do i have to?
Depends. The default one just calls operator= for each class member (Which is just a copy for primtive types). If you need different behaviour (If you have any pointers as members, this is likely), you'll need to provide your own assignment operator.

Share this post


Link to post
Share on other sites
ok thanks.

yes i am using pointers as members of this class.

would changing the situation to a pointer solve my problem?


myClass* foo = new myClass();
foo->operateOnArray();

foo = new myClass();
foo->operateOnArray();



will the destructor be correctly called on the OLD object?

basically i just want to create a new instance and save it in the variable foo, while the old instance gets its destructor called correctly.

thanks!

Share this post


Link to post
Share on other sites
Quote:
Original post by ehmdjii
ok thanks.

yes i am using pointers as members of this class.

would changing the situation to a pointer solve my problem?

*** Source Snippet Removed ***

will the destructor be correctly called on the OLD object?

basically i just want to create a new instance and save it in the variable foo, while the old instance gets its destructor called correctly.

thanks!
No destructor will be called in the above code because the object is on the heap. The destructor will be called by delete, or if you call it manually (Which isn't something you want to be doing). That code will cause a memory leak unless you add a delete call:

myClass* foo = new myClass(); // Create a new myClass obj on the heap. Assign address to foo
foo->operateOnArray();
delete foo; // Delete foo: call destructor and free memory. foo is now an invalid pointer

foo = new myClass(); // Create a new myClass obj on the heap. Assign address to foo
foo->operateOnArray();



What exactly are you trying to do here? Generally if assignment is expensive (Which can be the case when you have pointers to dynamic memory as members, since you may need to reallocate that memory) you'd use pointers to objects, and objects otherwise.

I'd also recommend looking into smart pointers (Boost has a few types), which may solve your problems.

Share this post


Link to post
Share on other sites
No, you didn't delete the old object, so the destructor isn't called.

That is known as a leak.

When you call "new", you are now in charge of making sure that object is deleted at the end of it's lifetime.

...

Some advice on constructors and destructors.

First, make sure everything your copy constructor does you deal with in your destructor, AND everything your default constructor does you deal with in your destructor. Realize that the object you copied from will still exist after the copy constructor.

In short: your copy constructor AND your default constructor AND every other constructor should allocate the same resources, usually.

Then your destructor cleans them up.

Next, operator= -- ie, the assignment operator.

An easy way to write operator= that doesn't screw up is to first write a "swap" function.


class foo {
public:
void swap(foo& other) { ... };
// ...
};

What swap does is it, well, swaps. It takes all of the resources owned by this, and all of the resources owned by other, and swaps who owns each. The state of the two objects changes hands.

Use of the #include <algorithm> std::swap is useful when implementing your own swap. :)

Now, you can write a really simple operator=:

class foo {
public:
foo& operator=(const foo& other) {
foo tmp = other; // copy constructor
this->swap(tmp); // swap our state
return *this; // the tmp object is destroyed, taking our resources with us!
}
};


Slick, eh? You move the tricky resource management code out of the operator=, and into the constructor/destructor only. The only disadvantage is that you don't get to recycle resources -- but the increased simplicity of code is often worth it.

Share this post


Link to post
Share on other sites
Quote:
Original post by NotAYakk
Now, you can write a really simple operator=:

class foo {
public:
foo& operator=(const foo& other) {
foo tmp = other; // copy constructor
this->swap(tmp); // swap our state
return *this; // the tmp object is destroyed, taking our resources with us!
}
};
I presume this:
foo tmp = other; // copy constructor
Should be this:
foo tmp(other); // copy constructor
?

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Quote:
Original post by NotAYakk
Now, you can write a really simple operator=:

class foo {
public:
foo& operator=(const foo& other) {
foo tmp = other; // copy constructor
this->swap(tmp); // swap our state
return *this; // the tmp object is destroyed, taking our resources with us!
}
};
I presume this:
foo tmp = other; // copy constructor
Should be this:
foo tmp(other); // copy constructor
?

Unless the copy constructor is marked as explicit, in which case the first in is a compile error, then they do the same thing; both are copy constructions.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement