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 temporary is constructed using whatever two-argument constructor matches
(a,b). foois constructed using the copy-constructor, passing the temporary as argument.- The temporary is destroyed.
Or
foois 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);
- A temporary is constructed using whatever two-argument constructor matches
(c,d). - The assignment operator for class
Objectis called onfoo, passing the temporary as argument. - The temporary is destroyed.
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?.
Yes, you're forgetting that you can overload the assignment operator. The one provided by default by the compiler simply copies blindly all the fields of the objects, but you can provide your own that will do whatever you want, including disposing the resources of the object target of the assignment.
Notice that it's easy to get wrong an assignment operator (forgetting about corner cases, exception safety, ...), I advise you to read at least this part of our operator overloading FAQ, which in turn redirects to the explanation of the common copy and swap idiom, which is almost always the only sensible way to implement the assignment operator.
Edit
See in addition @Steve Jessop's answer, that considers another fundamental misunderstanding.
In all cases in which you write
SomeClass sc = SomeClass(parameters);
you are initializing a new object: you're creating a temporary (SomeClass(parameters)) and then initializing sc with a copy of it (via the copy constructor); this is both unnecessary and inefficient, the syntax to create an object on the stack in C++ is just
SomeClass sc(parameters);
Delegate calculation of DelayObject parameters to private (possibly static) methods and use them when constructing DelayObject in initializer list.
加载中,请稍侯......
精彩评论