lambda
lambda

Reputation: 1235

C++ Pointers and Deletion

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

Answers (7)

QT-ITK-VTK-Help
QT-ITK-VTK-Help

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

CB Bailey
CB Bailey

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

TobiMcNamobi
TobiMcNamobi

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

Adrian Shum
Adrian Shum

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

Suvarna Pattayil
Suvarna Pattayil

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

user2379182
user2379182

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

nurettin
nurettin

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

Related Questions