删除后对象不指向NULL

Zha*_*man 1 c++ pointers linked-list nullptr

我有Node课。成员是int id, 和指向下一个节点的指针:Node* next。我按如下方式实现了构造函数和析构函数:

#include <iostream>

class Node
{
public:
  int id;
  Node *next;
  Node() : id(0), next(nullptr) {}
  explicit Node(int id) : id(id), next(nullptr) {}

  ~Node() {
    std::cout << (*this) << " destructed \n";
    delete next;
    next = nullptr;
  }

  friend std::ostream &operator<<(std::ostream &os, const Node &node) {
    os << "Node(" << node.id << ")";
    return os;
  }
};

int main()
{
  Node *node0;
  Node *node1;
  node0 = new Node(0);
  node1 = new Node(1);
  node0->next = node1;

  delete node0; // outputs Node(0) destructed\nNode(1) destructed
  node0 = nullptr;
  std::cout << (nullptr == node0) << '\n'; // outputs 1
  std::cout << (nullptr == node1) << '\n'; // outputs 0
  std::cout << *node1 << " \n"; // outputs Node(8430)
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我认为node1应该已经指向 ,nullptr因为在调用 的析构函数时node0,它的下一个被删除并指向nullptr,但输出表明node1显然是 Node(8430) 而不是nullptr

我知道取消引用 a 时nullptr可能会导致未定义的行为。我怎样才能修改这个程序,以便在调用delete之后node0node1也可以变成nullptr

for*_*818 7

您所期望的与此类似:

void foo(int* ptr) {
    delete ptr;
    ptr = nullptr;
}

int main() {
   int * x = new int;
   foo(x);
   assert( x == nullptr);   // NOPE !!
}
Run Code Online (Sandbox Code Playgroud)

ptr是 的副本xdelete ptr删除动态分配的int. x这不会以任何方式影响 的价值。x调用后仍然具有相同的值foo。它不再是一个有效的指针了。它所指向的地址不再存在int

或者更简单:

int* a = new int;
int* b = a;
delete a;
a = nullptr;
assert( b == nullptr ); // NOPE !!!
Run Code Online (Sandbox Code Playgroud)

其实你的误解可以追溯到一个更简单的例子:

int a = 42;
int b = a;
a = 0;
assert( b == 0); // NO !!
Run Code Online (Sandbox Code Playgroud)

对于指针来说,这没有什么不同。

在您的代码中node0->next = node1;创建了指针的副本。然后在析构函数中node0删除 指向的节点node0->next,但这对 main 中的指针没有影响。

TL;DR:不要混淆指针和受指点。delete x删除 指向的对象x。如果复制一个指针,就会有两个完全独立的指针指向同一个对象,分配nullptr给其中一个指针不会对另一个指针产生影响。

  • @ZhangColeman 不,没有办法。原始拥有指针的替代品是“std::unique_ptr”。`std::shared_ptr` 用于共享所有权 (3认同)
  • @ZhangColeman *我认为删除后,指针应该为 nullptr;* - 当发出“delete”时,C++ 不会浪费周期将指针设置为“nullptr”。如果我编写 C++ 代码,我不希望 C++ 做我没有要求的额外事情,尤其是那些会降低性能的事情。这就是 C++ 哲学——它被称为[零开销原则](https://en.cppreference.com/w/cpp/language/Zero-overhead_principle#:~:text=The%20zero%2Doverhead%20principle% 20是,可以%20合理地%20手写%20。) (2认同)