🔒 Locked
Constructors/Destructors
Advertisement
Original Post
Hi,
I am having problems using destructors. I have a class constructor in which i initialise my objects:
Triangle::Triangle(Vector3D X, Vector3D Y, Vector3D Z)
{
this->v0 = new Vector3D(X);
this->v1 = new Vector3D(Y);
this->v2 = new Vector3D(Z);
}
and a destructor to delete the objects
Triangle::~Triangle()
{
delete v0;
delete v1;
delete v2;
}
This code causes an ''assertion failure'' and i dont understand why this code doesnt work, can anyone help? If i remove the delete commands from the destructor it all works fine!
Thanks
quote:
Original post by MrWendell1982
This code causes an ''assertion failure'' and i dont understand why this code doesnt work, can anyone help? If i remove the delete commands from the destructor it all works fine!
If you need to write a destructor, you also need to write a copy constructor and an assignment operator.
Actually
if ( v1 ) delete v1;
should just be
delete v1;
Calling delete with a null pointer is perfectly valid C++, so the if-statement is completely pointless.
You really do need to implement a copy constructor and an assignment operator, like so (extending the previous examples):
Triangle::Triangle(const Triangle ▵)
{
v1 = new Vector3D(triangle.v1);
v2 = new Vector3D(triangle.v2);
v3 = new Vector3D(triangle.v3);
}
void Triangle::operator=(const Triangle ▵)
{
delete v1;
delete v2;
delete v3;
v1 = new Vector3D(triangle.v1);
v2 = new Vector3D(triangle.v2);
v3 = new Vector3D(triangle.v3);
}
Of course, a better assignment operator would go something like:
void Triangle::operator=(const Triangle ▵)
{
v1->Set(triangle.v1);
v2->Set(triangle.v2);
v3->Set(triangle.v3);
}
HTH,
Jim Offerman
lead developer
Crevace Games
www.crevace.com
[edited by - jofferman on April 24, 2003 9:19:55 AM]
if ( v1 ) delete v1;
should just be
delete v1;
Calling delete with a null pointer is perfectly valid C++, so the if-statement is completely pointless.
You really do need to implement a copy constructor and an assignment operator, like so (extending the previous examples):
Triangle::Triangle(const Triangle ▵)
{
v1 = new Vector3D(triangle.v1);
v2 = new Vector3D(triangle.v2);
v3 = new Vector3D(triangle.v3);
}
void Triangle::operator=(const Triangle ▵)
{
delete v1;
delete v2;
delete v3;
v1 = new Vector3D(triangle.v1);
v2 = new Vector3D(triangle.v2);
v3 = new Vector3D(triangle.v3);
}
Of course, a better assignment operator would go something like:
void Triangle::operator=(const Triangle ▵)
{
v1->Set(triangle.v1);
v2->Set(triangle.v2);
v3->Set(triangle.v3);
}
HTH,
Jim Offerman
lead developer
Crevace Games
www.crevace.com
[edited by - jofferman on April 24, 2003 9:19:55 AM]
as far as I know (and looking to this thread, what I know is wrong)
1. You do NOT need to write copy ctor and assignment operator if you need to write destructor. But that''s SabreMan, so it should be correct. Can I have some more info on that SabreMan?
2. You can safely delete NULL pointers..
IMHO, OP''s actual problem is not in that piece of code, but he is probably deleting or writing over those pointers in somewhere else.
comments?
1. You do NOT need to write copy ctor and assignment operator if you need to write destructor. But that''s SabreMan, so it should be correct. Can I have some more info on that SabreMan?
2. You can safely delete NULL pointers..
IMHO, OP''s actual problem is not in that piece of code, but he is probably deleting or writing over those pointers in somewhere else.
comments?
deleting a zero pointer (or NULL) does nothing.
Why do you need to store the vectors as pointers anyway? Why not just:
?
Why do you need to store the vectors as pointers anyway? Why not just:
class Triangle {
//...
Vector3D v0;
Vector3D v1;
Vector3D v2;
}
?
quote:
Original post by mentat
1. You do NOT need to write copy ctor and assignment operator if you need to write destructor.
If you have to write a destructor, then it is to clean-up dynamically allocated resources. The default copy ctor and assignment operator operate on a member-wise basis, which means they perform shallow copy (they just copy the value of the pointers, not what they point to). So, imagine you have an object A1 which refers (via a pointer) to another object B. Then you create a shallow copy of A1 and call it A2. When A1''s lifetime expires, the destructor deletes B. When A2''s lifetime expires, it also deletes B. Whoops! If the copy constructor for A1 and A2 were to perform deep-copy, then A2 would receive it''s own copy of B, which it can quite safely delete in the knowledge A1 won''t be deleting the same B.
The rule which says "if you need one of the copy ctor, assignment op or dtor, then you probably need all three" is called the Rule of Three. There are exceptions to this rule, but I don''t think we have one here.
I believe sabreman is largely correct. Usually you only NEED to make a destructor when your class dynamically allocates memory for itself...
...If this is the case and you do not write a copy constructor/assignment operator then the default ones will perform naive copies instead of deep copies...
...With a naive copy only the pointer is copied and you have two or more instances of a class with a pointer pointing to the same memory...
...A deep copy assignes new memory for the new instance and copies the contents of the source objects dynamically allocated memory into that...
SOMETIMES you MIGHT want a naive copy but 99% of the time you want a deep copy. It is a very important concept in C++.
Geocyte Has Committed Suicide.
...If this is the case and you do not write a copy constructor/assignment operator then the default ones will perform naive copies instead of deep copies...
...With a naive copy only the pointer is copied and you have two or more instances of a class with a pointer pointing to the same memory...
...A deep copy assignes new memory for the new instance and copies the contents of the source objects dynamically allocated memory into that...
SOMETIMES you MIGHT want a naive copy but 99% of the time you want a deep copy. It is a very important concept in C++.
Geocyte Has Committed Suicide.
A default constructor won''t make any difference. Where would it be being called in this example?
Destructors are always called for any object created unless the program crashes. If they are not explicitly called they will be called automatically when the object goes out of scope. For example...
int main()
{
myClass myObject;
} // <--destructor for myObject is called here.
Geocyte Has Committed Suicide.
[edited by - geocyte on April 24, 2003 12:42:38 PM]
int main()
{
myClass myObject;
} // <--destructor for myObject is called here.
Geocyte Has Committed Suicide.
[edited by - geocyte on April 24, 2003 12:42:38 PM]
Geocyte, you''re making wild generalisations.
not always
not always
You''re talking about objects on the stack. Objects on the heap won''t have their destructors called.
If a program throws an exception (which if its unhandled will most likely cause the program to crash), objects on the stack will be destroyed correctly.
quote:
Destructors are always called for any object created...
not always
quote:
...unless the program crashes
not always
You''re talking about objects on the stack. Objects on the heap won''t have their destructors called.
If a program throws an exception (which if its unhandled will most likely cause the program to crash), objects on the stack will be destroyed correctly.
Yes you are both right. Naturally I wasn't talking about dynamically allocated objects but failed to make this clear. My apologies for my sloppy English.
Also, for some reason I appear to have been mis-reading things as well a mis-writing them as I read "constructor" as "destructor" in your comment "A default constructor won't make any difference.". Sorry. In fact you are right there as well since the default constructor triangle() is not called in the example given. My apologies for my sloppy eyes.
Geocyte Has Committed Suicide.
[edited by - geocyte on April 24, 2003 3:11:11 PM]
Also, for some reason I appear to have been mis-reading things as well a mis-writing them as I read "constructor" as "destructor" in your comment "A default constructor won't make any difference.". Sorry. In fact you are right there as well since the default constructor triangle() is not called in the example given. My apologies for my sloppy eyes.
Geocyte Has Committed Suicide.
[edited by - geocyte on April 24, 2003 3:11:11 PM]
quote:
Geocyte:
Yes you are both right. Naturally I wasn''t talking about dynamically allocated objects but failed to make this clear. My apologies for my sloppy English.
If you were talking about stack objects then you were incorrect about destructors not being called when the program crashes. Your English is fine (c:
Generalisations are almost always inadequate expressions.
I am having the same problem, but I am still confused as to what is occuring. In fact, isn't having new() in a constructor and delete() in a destructor the most basic simple use of these commands? I could swear I've done it a gillion times with no problem or overloading of other things. My whole dynamic allocation world is turned on its head! (cry)
Anyway in the triangle example I don't see where he is making copies that are both calling the destructor. He makes one copy in the constructor, and deletes it in the destructor. Where is the shallow copy being done? Also, if its valid to call the delete on a null pointer whats wrong with the shallow copy anyway
If you could explain a little better exactly where the problem crops up in his ULTRA simple example it would help me a lot.
Also, if you remove the destructor delete calls, the errors go away. Does this mean you have no leak now, or a worse leak? hehe.
[edited by - aargyle on April 25, 2003 3:15:18 AM]
Anyway in the triangle example I don't see where he is making copies that are both calling the destructor. He makes one copy in the constructor, and deletes it in the destructor. Where is the shallow copy being done? Also, if its valid to call the delete on a null pointer whats wrong with the shallow copy anyway
Also, if you remove the destructor delete calls, the errors go away. Does this mean you have no leak now, or a worse leak? hehe.
[edited by - aargyle on April 25, 2003 3:15:18 AM]
quote:
I am having the same problem, but I am still confused as to what is occuring.
Somewhere along the line, those pointers are being deleted prematurely. Either it's because one of his member functions deleted them already and forgot to clean-up the pointers by setting them to zero, or another object got a copy of the pointers are deleted them first. If he can confirm that the memory isn't being released from other member functions, then it's most likely a copy problem.
Even if he isn't explicitly assigning or copying his object, it can happen "automatically." For example, pass your object by-value to a function and it's copied. Return a temporary by-value from a function and it's copied.
Having
new in the constructor and delete in the destructor is the simpliest example of dynamic memory allocation combined with classes. However, even such a simple situation requires all the extra maintanence if you plan to use it in non-trivial ways. And most the time, many beginners use them in non-trivial ways, and bad side effects can occur if they're not careful.quote:
Also, if its valid to call the delete on a null pointer whats wrong with the shallow copy anyway
Each object that uses dynamic allocation should maintain it's own copy of the data. When you copy an object, it's the object's responsibility to make sure all dynamically allocated data is duplicated as well. A shallow copy usually suits quite well, because a lot of the time the object contains the storage it needs to maintain unique copies of the data, and the copy is handled automatically by the compiler. This includes pointers, yet what they point to is what is important, and if that value is copied, the memory it points to is not unique.
quote:
If you could explain a little better exactly where the problem crops up in his ULTRA simple example it would help me a lot.
Somewhere in code we can't see.
[edited by - Zipster on April 25, 2003 3:30:39 AM]
quote:
Original post by petewood
If you were talking about stack objects then you were incorrect about destructors not being called when the program crashes.
That depends on what is meant by a "crash". If you mean program termination in the face of an unhandled exception then yes, the stack will be unwound. If you mean OS faults due to things like out-of-bounds accesses, then you have no guarantee stack unwinding will take place.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement