简体   繁体   中英

deleting object pointed to by two differnet pointers

I have created one Node object and the pointer named head is pointing to it. Then another pointer named newHead is created which points to the same object. Then I delete the memory by doing delete head and reassign head to a nullptr . However, this change is not reflected by the newHead pointer. From the attached code it is evident that newHead is not a nullptr and accessing the member value returns garbage value.

To understand this problem, I have already gone through this post which states that

Also note that you can delete the memory from any pointer that points to it

which is evidently not the case for the attached code below. Further I know that using smart pointers will definitely one way to resolve the issue, but in my application, I do need to use a raw pointer.

Any help in giving me an understanding of why is this happening and how to resolve it will be appreciated. Thank you.

#include <iostream>
using namespace std;

class Node {
public:
  Node(int value) {this->value = value;}
  int value;
  Node* next = nullptr;
};

int main(int argc, char** argv) {
  // create a node object
  Node* head = new Node(5);

  // another pointer pointing to head
  Node* newHead = head;

  // delete the object pointed to by head
  delete head;
  head = nullptr;

  // check if newHead is nullptr
  if (newHead == nullptr) {
    std::cout << "newHead is a nullptr" << std::endl;
  }
  else {
    std::cout << "Head is not a nullptr" << std::endl;
    std::cout << "Node value is: " << newHead->value << std::endl;
  }

  return 0;
}

The two pointers were pointing to the same memory, the nullptr is not put in there instead of the deleted object.

head = nullptr; // this is not putting nullptr where the deleted object was!

This is why, newHead is not pointing to nullptr but to a released memory.


What you want is a Reference to pointer

// CPP program to demonstrate references to pointers. 
#include <iostream> 
using namespace std; 

int main() 
{ 
    int x = 10; 

    // ptr1 holds address of x 
    int* ptr1 = &x; 

    // Now ptr2 also holds address of x. 
    // But note that pt2 is an alias of ptr1. 
    // So if we change any of these two to 
    // hold some other address, the other 
    // pointer will also change. 
    int*& ptr2 = ptr1; 

    int y = 20; 
    ptr1 = &y; 

    // Below line prints 20, 20, 10, 20 
    // Note that ptr1 also starts pointing 
    // to y. 
    cout << *ptr1 << " " << *ptr2 << " "
        << x << " " << y; 

    return 0; 
} 

Output:

20 20 10 20

Credit to geeksforgeeks

In contrast, having

int* ptr2 = ptr1; 
int y = 20; 
ptr1 = &y; 

Gives

20 10 10 20

If you delete the memory pointed by one or more pointers, the pointer values don't change. You can test this by checking the value pointer before and after the execution of the delete statement.

There's no way to (without saving some meta information somewhere) to know how many or what pointers are still pointing to some memory buffer.

The approach followed by this class of objects (that get pointed to from different places) is to have a count of the number of pointers you still have pointing to the buffer. When you assing a new reference, you increment the pointer, and when you delete one reference, you decrement it, and, only when the count of reference pointers is about to reach 0, then you actually delete it.

It's not complicated to use this technique to implement dynamic classes like trees or more abstract. I used it to implement a string type, years ago, with a copy on write semantics that allowed you to save copying string contents on mostly readonly strings.

I have created one Node object and the pointer named head is pointing to it. Then another pointer named newHead is created which points to the same object. Then I delete the memory by doing delete head and reassign head to a nullptr. However, this change is not reflected by the newHead pointer. From the attached code it is evident that newHead is not a nullptr and accessing the member value returns garbage value.

Right. Nowhere in your code in your code to you change newHead s value, so it still has the same value it had before. Of course, it is an error to access the member value because the object no longer exists.

To understand this problem, I have already gone through this post which states that

Also note that you can delete the memory from any pointer that points to it

which is evidently not the case for the attached code below.

Why do you say that? That's exactly what happened in your code. You had two pointers that point to the same block of memory and you could have used either to free it. You used one of them, and it was freed.

Any help in giving me an understanding of why is this happening and how to resolve it will be appreciated. Thank you.

You never change the value of newHead , so it contains the same value it had before you called free . Only after you call free , that object no longer exists, so it's a useless garbage value.

It's not clear what you don't understand. After you free a block of memory, it is an error to access it. The solution is simple -- don't do that . After you do delete head; , both head and newHead point to memory that is no longer allocated. You set head to nullptr , but you don't change newHead 's value, so it still points to where the memory used to be.

If you are going to use malloc or new , it is your responsibility to track the lifetimes of objects and not access them outside their lifetimes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM