I've learned from experience to use an auto_ptr instead of a raw
pointer for my class variables, as follows -
class Person
{
public:
Person(const bool isSingle=true):lover(isSingle?0:new Lover() ){}
private:
const auto_ptr<Lover> lover;
}
since its a very good approach to avoiding memory leaks.
But what about when that pointer points to memory allocated using new
[]?
private:
const auto_ptr<Lover> lover;
const Offspring* offspring;
const CompirerErrors* compirerErrors;
how would you normally deal with such a case with regard to avoiding
memory leaks?
For example -
Person me;
Person imposter;
imposter = me;
might leak when operator=() throws - when calling new, or when
assigning each member of offspring and compirerErrors.
Therefore how should I implement operator=()? How about this as a
generic solution to memory leakage in operator=()?
Person& operator=(const Person& person)
{
if(person==this)
return this;
try
{
Offspring* tempOffspring = new Offspring[noOfOffspring];
CompirerErrors* tempCompirerErrors = new CompirerErrors
[noOfCompilerErrors];
for(int i = 0; i<noOfOffspring;i++)
tempOffspring[i] = person.tempOffspring[i];
for(int i = 0; i<noOfCompilerErrors;i++)
tempCompirerErrors[i] = person.compirerErrors[i];
}
catch(...)
{
delete [] tempOffspring;
delete [] noOfOffspring;
throw PersonException();
}
offspring = tempOffspring;
compirerErrors = tempCompirerErrors;
...
}
It depends on the copying policy you want to use.
If copying is disabled, or if a deep copy is always performed, just
use std::vector. No need to reinvent the wheel.
If you want the array to be shared, I think there's a smart pointer
for that purpose in the boost library. You could relatively easily code
one yourself.
If you want the ownership to be transferred, implement your own
auto_array (if you google that name you'll probably find implementations
made by others).
If you want copy-on-write, then you'll have to implement that yourself.
Thanks for your reply. Since I'm still learning, does the code I
provided in my first post avoid memory leakage? I had taught about
using std::vector actually in this fashion -
private:
std::vector<Offspring> offspring;
std::vector<CompirerErrors> compirerErrors;
...
Person& operator=(const Person& person)
{
if(person==this)
return this;
try
{
tempPerson.offspring = person.tempOffspring;
compirerErrors = person.compirerErrors;
}
catch(...)
{
throw PersonException();
}
...
}
But if -
tempPerson.offspring = person.tempOffspring
were to throw an exception here, wouldn't I end up with a Person
object which is in a corrupt state? How should I deal with this.
Thanks again,
Barry
copy and swap paradigm.
> But what about when that pointer points to memory allocated using new
> []?
>
> private:
> const auto_ptr<Lover> lover;
> const Offspring* offspring;
> const CompirerErrors* compirerErrors;
>
> how would you normally deal with such a case with regard to avoiding
> memory leaks?
Very simple: I would not use new, unless absolutely necessary.
I'd estimate that 90% of the time, explicit memory allocation/deallocation
can be replaced with containers.
I've taken over countless projects that leaked memory like a sieve.
Although, after a careful inspection, the memory leaks were obvious, and the
fixes were also obvious, I usually defenestrated the whole mess and replaced
the brain-dead contain with clean usage of STL containers.
I always run into issues with polymorphic objects when I go that route.
Perhaps I should use a pimpl approach?
--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>