When a variable is reassigned, the destructor is not called:
Object foo = Object(a,b);
foo = Object(c,d);
so, the destructor will only be called at the end of the scope for Object(c,d), which can obviously cause problems. Now, in this specific case it doesn't bother me too much: it is enough to declare 2 different objects:
Object foo1 = Object(a,b);
Object foo2 = Object(c,d);
In this way the destructor of both objects will be called at the end.
However, there is a case when I necessarily need to reassign a variable, i.e. in an object constructor such as:
SuperObject(Point point1, Point point2) : delay_object_(DelayObject(0)) {
double distance = distance(point1, point2);
double delay = distance / speed;
delay_object_ = DelayObject(delay);
}
In fact the DelayObject parameter is not easy to calculate (in this example I also omitted a few other passages), and I want to avoid doing it in the initialisation list.
I thought I can force the deletion by putting the object in the heap and explicitly calling the destructor:
SuperObject(Point point1, Point point2) : p_delay_object_(new DelayObject(0)) {
double distance = distance(point1, point2);
double delay = distance / speed;
delete p_delay_object_;
p_delay_object_ = new DelayObject(delay);
}
but this really looks ugly to me, as I prefer to use dynamic allocation only when strictly necessary. Am I missing something?
Cheers!
"the destructor will only be called at the end of the scope for Object(c,d)"
False. Object(c,d)
is a temporary, and its destructor is called at the end of the full-expression which creates it. In this case, that's the semi-colon at the end of foo = Object(c,d);
. The destructor of foo
is called at end-of-scope.
The assignment operator of Object
should free or re-use resources already held by foo
, and copy resources held by the temporary. Not necessarily in that order (see copy-and-swap).
Edit: in response to comment.
Object foo = Object(a,b);
Either
(a,b)
.foo
is constructed using the copy-constructor, passing the temporary as argument.Or
foo
is constructed using whatever two-argument constructor matches (a,b)
.The implementation is free to do either - this is permitted by "copy constructor elision".
foo = Object(c,d);
(c,d)
.Object
is called on foo
, passing the temporary as argument.Some time later, at the end of the scope, foo
is destroyed.
In C++0x, move assignment would come into play if it exists for the class.
You should overload the assignment operator, which would, conceptually, copy construct the existing object and destroy the old 'this'.
class Object {
...
Object& operator= (const Object& other) {
if (this != &other) {
// copy 'other' into 'this'.
}
return *this;
}
...
};
then the foo = Object(c,d);
line should do what you expect.
(Also as @Steve Jessop mentioned, the temporary object Object(c,d)
will also be destructed after before the end of the scope.)
See What is The Rule of Three?.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With