| | |
Constructor and Convertion operator are the same,how to avoid memory leak?
![]() |
•
•
Join Date: Aug 2004
Posts: 13
Reputation:
Solved Threads: 0
Hi
I created a class,simplified class is like below:
#include<iostream.h>
class cCat
{
public:
//Constructors and Destructors
cCat();
~cCat();
//Accessor Function
int & cCat::GetAge() const{ return *itsAge;}
//Convertion operator
cCat(int); // cCat object =int x
private:
int *itsAge;
};
cCat::cCat()
{
itsAge = new int;
*itsAge= 20;
}
cCat::~cCat()
{
}
//Convertion Operator
cCat::cCat(int Age)
{
itsAge= new int;
*itsAge=Age;
}
main()
{
cCat MyCat(23);
cout<<"My Cat age:"<<MyCat.GetAge();
MyCat=42; //this makes a memory leak
return 0;
}
As the code shows MyCat(23) and MyCat=42 statements have the same definition in the class and this makes a memory leak.(cause without deleting previous allocated memory I allocate a new memory in cCat(int Age)
so,how can I avoid this memory leak?
I created a class,simplified class is like below:
#include<iostream.h>
class cCat
{
public:
//Constructors and Destructors
cCat();
~cCat();
//Accessor Function
int & cCat::GetAge() const{ return *itsAge;}
//Convertion operator
cCat(int); // cCat object =int x
private:
int *itsAge;
};
cCat::cCat()
{
itsAge = new int;
*itsAge= 20;
}
cCat::~cCat()
{
}
//Convertion Operator
cCat::cCat(int Age)
{
itsAge= new int;
*itsAge=Age;
}
main()
{
cCat MyCat(23);
cout<<"My Cat age:"<<MyCat.GetAge();
MyCat=42; //this makes a memory leak
return 0;
}
As the code shows MyCat(23) and MyCat=42 statements have the same definition in the class and this makes a memory leak.(cause without deleting previous allocated memory I allocate a new memory in cCat(int Age)
so,how can I avoid this memory leak?
Heck, your destructor causes a memory leak too. You should delete age there.
There may be good reasons for a pointer to int here, but in this simple example an int would work fine, wouldn't it? But, assuming there's more to this....
= is an assignment operator, so it doesn't go through the constructor code. Since you don't define an assignment operator, the compiler figured out that it could turn the int into a cCat by calling the constructor, and then it could just copy en-masse the bytes over. Another leak!
Add an assignment operator:
cCat& operator = ( int age ) { *itsAge = age; return this; }
(I didn't try this out in the compiler, but you can get the syntax right when you do)
Remember that in an assignment operator, the object has already been constructed. As opposed to a copy constructor, in which the object has not already been constructed. The compiler will supply a default if it can, and the default will NOT be sensitive to allocated ram.
There may be good reasons for a pointer to int here, but in this simple example an int would work fine, wouldn't it? But, assuming there's more to this....
= is an assignment operator, so it doesn't go through the constructor code. Since you don't define an assignment operator, the compiler figured out that it could turn the int into a cCat by calling the constructor, and then it could just copy en-masse the bytes over. Another leak!
Add an assignment operator:
cCat& operator = ( int age ) { *itsAge = age; return this; }
(I didn't try this out in the compiler, but you can get the syntax right when you do)
Remember that in an assignment operator, the object has already been constructed. As opposed to a copy constructor, in which the object has not already been constructed. The compiler will supply a default if it can, and the default will NOT be sensitive to allocated ram.
•
•
Join Date: Aug 2004
Posts: 13
Reputation:
Solved Threads: 0
Hi
Thanks for your help
I used a reference to int cause my int doesn't go out if scope after returning of my function so I tried to do this to avoid making a temporary int , and program be faster ,If I am wrong tell me ,I would be happy to know.
and about destructors, I saw some codes of a book that where written like this (I in destructors no delete wasn't suppied).
I think that it wouldn't make a memory leak cause my objects stay alife to end of the program and at end of it memory will become freed automatically
except when I create a pointer to my class,and allocate memory for it
are these corrrect?
thanks for your helps again
Thanks for your help
I used a reference to int cause my int doesn't go out if scope after returning of my function so I tried to do this to avoid making a temporary int , and program be faster ,If I am wrong tell me ,I would be happy to know.
and about destructors, I saw some codes of a book that where written like this (I in destructors no delete wasn't suppied).
I think that it wouldn't make a memory leak cause my objects stay alife to end of the program and at end of it memory will become freed automatically
except when I create a pointer to my class,and allocate memory for it
are these corrrect?
thanks for your helps again
About the ptr to int/ref to int thing: the memory allocated for the class instance of cCat holds, in your case, a pointer. But holding an int is really the same in terms of what happens to the CLASS instance; if you return a cCat from a function the out-of-scope stuff still applies whether a member of the class is a pointer or not.
So, in this case, I think an int is perfectly adequate. If you had issues with returning the cCat from a routine, you might want to do a new on the whole cCat object, and return a pointer to the cCat. Like this:
and then the caller has to 'delete' the return value when she's done. Generally, it would be easier to use something like this, unless there is a benefit for the allocated memory:
As to the destructor, you are correct that, in this specific case, the memory is freed when you exit your program. Though, when you originally mentioned a leak, the same thing would apply. You could leak a TON of memory and that would be ok since you exit the program.
Still, leaking ram is like running a stop sign. Someday you will get caught. Get in the habit of watching out for leaks and that good habit will save your keester someday.
Generally, if you allocate space in your class with new, you will want to:
a) set the pointer to NULL in your constructor, and
b) delete the pointer in your destructor, and
c) watch out for the assignment operator (do not let the compiler generate one for you, it will be wrong), and
d) make a copy constructor that allocates ram for the copy (again the compiler will be happy to generate the WRONG code for you)
If you put somthing in your destructor, you should also get in the good habit of declaring the destructor 'virtual' unless you have a clear reason for not doing that. Good reasons might include a tiny object that will NEVER have a subclass and there will be MILLIONS of them, so the saved pointer is truly a benefit.
a virtual destructor in this case also has no benefit yet, but if you do it as rote you won't make a mistake of that kind in a larger program where someone makes a subclass called 'cKitten' and you have a leak again.
Just sage advice.
So, in this case, I think an int is perfectly adequate. If you had issues with returning the cCat from a routine, you might want to do a new on the whole cCat object, and return a pointer to the cCat. Like this:
C++ Syntax (Toggle Plain Text)
cCat* GetACat(int age) { return new cCat(age); }
C++ Syntax (Toggle Plain Text)
void GetCat( cCat* myCat, int age ) { myCat->SetAge(age); } - or - void GetCatByRef( cCat& myCat, int age ) { myCat.SetAge(age); } To use, you would do something like this: cCat myCat; // local space, not allocated GetCat( &myCat, 23 ); // in the first version GetCatByRef( myCat, 23 ); // in the second version
As to the destructor, you are correct that, in this specific case, the memory is freed when you exit your program. Though, when you originally mentioned a leak, the same thing would apply. You could leak a TON of memory and that would be ok since you exit the program.
Still, leaking ram is like running a stop sign. Someday you will get caught. Get in the habit of watching out for leaks and that good habit will save your keester someday.
Generally, if you allocate space in your class with new, you will want to:
a) set the pointer to NULL in your constructor, and
b) delete the pointer in your destructor, and
c) watch out for the assignment operator (do not let the compiler generate one for you, it will be wrong), and
d) make a copy constructor that allocates ram for the copy (again the compiler will be happy to generate the WRONG code for you)
If you put somthing in your destructor, you should also get in the good habit of declaring the destructor 'virtual' unless you have a clear reason for not doing that. Good reasons might include a tiny object that will NEVER have a subclass and there will be MILLIONS of them, so the saved pointer is truly a benefit.
a virtual destructor in this case also has no benefit yet, but if you do it as rote you won't make a mistake of that kind in a larger program where someone makes a subclass called 'cKitten' and you have a leak again.
Just sage advice.
![]() |
Similar Threads
Other Threads in the C++ Forum
- Previous Thread: this shall be my last stupid q about progamming
- Next Thread: Help with Classes
| Thread Tools | Search this Thread |
api array assembly based basiccounter binary bitmap c++ c/c++ char class classes code coding compile console conversion count delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez graph gui homeworkhelp homeworkhelper iamthwee ifstream input int integer java lib linkedlist linker loop looping loops map math matrix memory multiple network news node opengl output pakistan parameter pointer problem program programing programming project python random read recursion reference rpg stream string strings subclass systray temperature template test text text-file thread traverse tree url variable vector video visualstudio2008 win32 windows winsock wordfrequency wxwidgets





