StandardG27
StandardG27

Reputation: 23

Delete dynamically allocated memory after swapping its pointer

I'm relatively new to C++ and I want to understand memory management and pointers at the same time.

Let's say I have the code below

int* p1;
int* p2;
int* p3 = new int[some size];

p1 = p3;

std::swap(p1,p2);

How do I properly delete the dynamically allocated memory? Is doing delete[] p3 enough? Should I delete p2 too after that?

Upvotes: 2

Views: 407

Answers (2)

i-hate-cookies
i-hate-cookies

Reputation: 47

To understand what is happening here, it would help to add some debug statements, i.e:

std::cout << p1 << " " << p2 << " " << p3 << "\n";

The trace will result in an output like:

0 0 0x15e7eb0
0x15e7eb0 0 0x15e7eb0
0 0x15e7eb0 0x15e7eb0

(Note that I initialized p1 and p1 to nullptr)

p3 initially points to some memory. After the assignment p1 = p3, p1 now points to the same memory address as p3. When you swap the pointers, now it's p2 that points to the same memory address as p3.

There are a couple of things to note here:

  • You must pair delete[] with the corresponding new[] (do not call delete with new[] and so forth)
  • Calling delete on an already deleted object is undefined behavior
  • Calling delete on a null pointer is perfectly safe

As you can see, dealing with raw pointers and memory allocation can easily lead to pitfalls. It's generally recommended to use smart pointers, or if you have a non-owning pointer, to use abstractions like observer_ptr to clearly indicate the pointer's purpose in the code.

Upvotes: 1

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122994

There is some fuzzyness in colloquial speech when you do something like this:

delete x;

We say "we delete x". Strictly speaking thats wrong, because what is deleted is the object pointed to by x.

Every object allocated via new/new[] must be destroyed via one call to delete/delete[]. Whether you have two or more pointers to the same object does not change that.

int* p1 = nullptr;
int* p2 = nullptr;
int* p3 = new int[some size];      // p3 points to the array

p1 = p3;                           // p1 points to the same array

std::swap(p1,p2);                  // now p1 == nullptr, p2 points to the array

Note that the pointers are uninitialized in your example. Reading their values causes undefined behavior. As this isnt the crux of the question I avoided that by initializing them.

There is one array created via new [] and it is that one array that you have to delete via delete []. You may not delete it twice. So either call delete[] p3; or delete[] p2;, but not both.

PS: Comments already mentioned smart pointers and I also suggest you to read about them. Nowadays you should not use raw owning pointers. An owning pointer is one that you need to call delete on, it "owns" the pointed to object. Raw pointers should only be used to "observe", ie you should never need to worry about calling delete (or delete[]) on a raw pointer. Of course you still need to take care whether the pointed to object is still alive, but that is not specific to dynamic allocation:

 int* p;
 { 
     int x = 42;
     p = &x;         // p points to x;
 }                   // x goes out of scope
 // here p is not a valid pointer anymore

Upvotes: 2

Related Questions