Reputation: 1235
This is a simplified version of some code that I have. Since pointerB
in class A
is set to pointer, beta
, in the client code which points to allocated memory, would i have to free the memory pointed by pointerB
in the destructor of class A
once it is deleted as well?
class A{
public:
A(B* beta){
pointerB = beta;
}
~A(){
/*
would deleting pointerB be necessary
*/
}
B* pointerB;
};
class B{
public:
B();
};
//client code
B* beta = new B();
A* alpha = new A(beta);
//do stuff
delete beta;
delete alpha;
beta = NULL;
alpha = NULL;
Upvotes: 1
Views: 125
Reputation: 558
You have to delete it in destructor of A. There is a sample program you can test both conditions by
1. Run the program still value of b exists means you have to delete it in destructor of A.
2. Uncomment delete b
line in the code and you will see b is free.
class B;
class A
{
B * b;
public:
A(B * obj)
{
b = obj;
}
~A()
{
//delete b;
}
};
class B
{
int value;
public:
B()
{
value = 10;
}
~B()
{
}
int getValue(){return value;}
};
void main()
{
B *b = new B;
A * a = new A(b);
delete a;
cout<<"B exists: "<<b->getValue();
}
Upvotes: 0
Reputation: 791361
It looks like objects of type A
retain a pointer to a B
object but don't own a B
. This is fine and A
's destructor shouldn't attempt to delete the B
object.
Given this model, the client should ensure that the B
object passed by pointer to A
's constructor remains in existence throughout the lifetime of the A
object. Your client code fails to do this but if you completely avoid dynamically allocating objects, achieving this is simple and natural and removes any possibility of leaking objects.
E.g.
void client()
{
B b;
A a(&b);
// do stuff
// Because we constructed `a` after we constructed `b` in this scope
// we are guarateed that `a` will be destroyed before `b` (reverse order)
// and the pointer that `a` is holding will never point to a destroyed
// object.
}
Upvotes: 2
Reputation: 4813
For every new
there has to be one and only one delete
during the execution of your application.
So it doesn't matter whether delete pointerB
is called in the destructor or delete beta
is called outside as you did. Because it is the same memory that is freed here! The question is if A "owns" an instance of B (and thus is responsible for freeing the memory it uses) or if A only has a reference to an instance of B (and is for example deleted when beta is still used).
BUT (as Roger already pointed out) I suggest reading the documentation to std::shared_ptr
and std::unique_ptr
. Here for example: http://en.cppreference.com/w/cpp/memory In most cases you can make good use of these and then you don't have to care for memory management.
Upvotes: 2
Reputation: 40036
The whole idea is, if you allocate something from heap, you should deallocate it and it should be done only once, and, you shouldn't access the memory after it is deallocated.
In order to achieve this, we usually make allocation and deallocation to be done by same component. For example, if you allocate a piece of memory in class Foo, do the deallocation there too. However, it is only a convention to make things less error-prone. As long as you are sure that the deallocation is going to happen, and happen only once, everything is fine.
Using shared_ptr or similar facilities is also a way to ensure this behavior.
Going back to your specific example, we cannot say whether you should do the deallocation in A. What I can say is, as you have delete beta
done in your main()
already, if you do the deallocation both in A
and main()
then it is a problem.
Whether you should deallocate in A
or leave it to the caller depends on your design.
Upvotes: 0
Reputation: 5239
When you allocate memory dynamically you have to release it.
When you do new B()
You allocate memory for the object dynamically and then assign the address to beta
which is of type B*
. This is a pointer to that memory. When you do delete beta
, you delete the memory that was allocated. This memory can be pointed by many pointers (like the one in your constructor )BUT you need to delete only once. But if you make attempts to use the other pointers (dereferencing etc.) you can blow your code.
Only when you do new
you allocate memory. [Your code must contain equal and corresponding number of delete
] which has to be released
Consider this way, you have a place for storing data and several labels pointing to the location of that place. Now if using one label you destroy the place, the other labels will still be having the location. But now its useless since the place is inexistent now.
Upvotes: 0
Reputation:
The assignment in the constructor of A
: pointerB = beta;
does not allocate new memory. Therefore, you do not need to de-allocate it when calling the destructor of A
.
However, this behavior is risky:
B* beta = new B(); // memory for B is allocated
A alpha( B ); // local instance. A.pointerB points to beta
delete beta; // memory de-allocated
// risky part: alpha.pointerB still points to where beta was allocated
// BUT THIS MEMORY IS ALREADY FREED!
You need to carefully think about this.
Upvotes: 1
Reputation: 11736
Your example can be simplified to this:
struct A{};
int main()
{
A* wtf= new A;
A* omg= wtf;
delete wtf;
}
Is correct and so is this:
struct A{};
int main()
{
A* wtf= new A;
A* omg= wtf;
delete omg;
}
Deleting both is a double delete error, don't do this:
delete omg;
delete wtf;
You would be trying to deallocate the same memory both pointers are pointing at, twice!
Upvotes: 0