Reputation: 14110
In my assignment operator method I first destroy any resources that the object manages, and then assign, so:
struct Animal
{
int aNumber;
int * buffer;
Animal() { buffer = new int[128]; }
Animal& operator= (Animal& other)
{
if (this != &other){
delete [] buffer;
//this->~Animal(); // I'm wondering if I can call this instead of deleting buffer here.
aNumber = other.aNumber;
}
~Animal() { delete[] buffer;}
};
The reason I'm asking this is so that instead of rewriting the deleting code, I can just have it in one place. Also, I don't think that calling the destructor deallocates the memory, so when I assign aNumber
after calling the destructor, I think it's OK. When I say the memory isn't deallocated I mean for example if I had a vector<Animal>
, and the vector
called the copy assignment operator for vector[0]
, vector[0]
Animal would call its own destructor and then assign aNumber
, but the memory is managed by vector (it's not deallocated). Am I right that the memory isn't deallocated?
Upvotes: 2
Views: 643
Reputation: 238411
I'm wondering if I can call [the destructor] instead of deleting buffer here.
You may not.
so when I assign aNumber after calling the destructor, I think it's OK
It is not OK. An explicit destructor call ends the lifetime of the object. You may not access members of an object after its lifetime has ended. The behaviour is undefined.
Am I right that the memory isn't deallocated?
You are right, but that doesn't matter.
The reason I'm asking this is so that instead of rewriting the deleting code, I can just have it in one place.
That can be achieved by writing a function that frees the resources, and call that function from both the assignment operator and the destructor.
Upvotes: 2
Reputation: 145379
After a destructor call the region of memory that held the object is just raw memory.
You can't use the result of just assigning to apparent members there.
It needs a constructor call to re-establish an object there.
But don't do this.
It's fraught with dangers, absolutely hostile deadly territory, and besides it's smelly and unclean.
Instead of
int* buffer;
Animal() { buffer = new int[128]; }
do
vector<int> buffer;
and expand that buffer as necessary as you add items to it, e.g. via push_back
.
A std::vector
automates the memory management for you, and does it guaranteed correctly. No bugs. Much easier.
In other news, the signature
Animal& operator= (Animal& other)
only lets you assign from non-const
Animal
objects specified with lvalue expressions (i.e. not temporaries), because only those can be bound the formal argument's reference to non-const
.
One way to fix that is to add a const
:
Animal& operator= (Animal const& other)
which communicates the intention to not modify the actual argument.
Upvotes: 4