简体   繁体   English

清除链表节点 class C++ 中的 function

[英]Clear function in a linked list node class C++

I am having trouble with making sure that I have created a clear function for a linked list Node class.我无法确保为链表节点 class 创建了明确的 function。 I am using delete this which I know can cause memory issues, but this is the only way that I can think of to assure that all of the objects in the linked list are deleted.我正在使用delete this ,我知道这会导致 memory 问题,但这是我能想到的确保删除链表中所有对象的唯一方法。 The final lines of main() will still print out the value of the head node that should have been deleted. main() 的最后几行仍然会打印出应该被删除的头节点的值。 Is this an error in the method or is this due to the pointer still being associated with the object?这是方法中的错误,还是由于指针仍与 object 相关联?

Clear method snippet清除方法片段

class Node {
private:
  Node *next = NULL;
  double value;
public:
  void clear();
};

void Node::clear() {
  cout << "Clear: " << this << ":" << value << endl;
  if(next != NULL){
    next -> clear();
  }
  delete this;
}

Full file完整文件


using namespace std;

class Node {
private:
  Node *next = NULL;
  double value;

public:
  Node(double);
  Node getNext(){return *next;} //inline
  void setNext(Node *newNext); //set *next
  double getValue(){return value;} //inline
  void setValue(double newValue) {value = newValue;} //inline
  void incValue(); //Increment value by the value of next node's value. If next is NULL do nothing.
  int sizeOf(); //return size of linked list
  double largest(); //return largest value in linked list
  double smallest(); //return smallest value in linked list
  double getSum(); //Get summation of all
  double average(); //return average of all values in the linked list
  void print(); //print all values in linked list
  void print_reverse(); //print all values in reverse order
  void clear(); //remove all nodes from linked list
};

Node::Node(double newValue) {
  value = newValue;
}
void Node::setNext(Node *newNext) {
  next = newNext;
}

void Node::incValue() {
  if(next != NULL) {
    double nextVal = next -> getValue();
    value += nextVal;
  }
}
int Node::sizeOf() {
  int count = 0;
  if(next != NULL)
    count = next -> sizeOf();

  count += 1;

  return count;
}
double Node::largest() {
  double large = value;
  if(next != NULL)
    large = next -> largest();

  if(value > large)
    large = value;

  return large;
}
double Node::smallest() {
  double small = value;
  if(next != NULL)
    small = next -> smallest();

  if(value < small)
    small = value;


  return small;

}
double Node::average() {
  double sum = getSum();
  int size = sizeOf();
  return sum/size;
}
double Node::getSum() {
  double sum = 0;
  int count = 0;
  if(next != NULL)
    sum += next -> getSum();
  sum += value;
  return sum;
}
void Node::print() {
  cout << value << endl;
  if(next != NULL)
    next -> print();
}
void Node::print_reverse() {
  if(next != NULL)
    next -> print_reverse();
  cout << value << endl;
}
void Node::clear() {
  cout << "Clear: " << this << ":" << value << endl;
  if(next != NULL){
    next -> clear();
  }
  delete this;
}




int main() {
  //set up linked list
  Node *head, *temp;
  temp = new Node(1);
  head = temp;
  temp = new Node(2);
  temp -> setNext(head);
  head = temp;
  temp = new Node(3);
  temp -> setNext(head);
  head = temp;
  temp = new Node(4);
  temp -> setNext(head);
  head = temp;
  temp = new Node(5);
  temp -> setNext(head);
  head = temp;
  temp = new Node(6);
  temp -> setNext(head);
  head = temp;
  temp = new Node(7);
  temp -> setNext(head);
  head = temp;
  temp = new Node(8);
  temp -> setNext(head);
  head = temp;
  //print
  cout << "Print\n";
  head -> print();
  //average
  cout << "Average\n";
  double av = head -> average();
  cout << av << endl;
  //print reverse
  cout << "Print reversed\n";
  head -> print_reverse();
  //smallest
  cout << "Smallest\n";
  double small = head -> smallest();
  cout << small << endl;
  //largest
  cout << "Largest\n";
  double  large = head -> largest();
  cout << large << endl;
  //size
  cout << "Size\n";
  int size = head -> sizeOf();
  cout << size << endl;
  //clear
  cout << "Clear\n";
  head -> clear();
  //clear print
  cout << "Clear print\n";
  head -> print();
  cout << "Clear size\n";
  cout << head -> sizeOf() << endl;

  //end of program
  cout << "End\n";
}

You should rarely (if ever) use delete this;你应该很少(如果有的话)使用delete this; . . You also do not clear the next pointer so it becomes a dangling pointer.您也没有清除next指针,因此它变成了一个悬空指针。 This memory likely still contains much of the data that was there, so when you traverse the list after "clearing" it, you're seeing the old data -- but note that this is only one of the many things that could happen, because accessing an object that has been destructed is undefined behavior.这个 memory 可能仍然包含那里的大部分数据,所以当你在“清除”它之后遍历列表时,你会看到旧数据——但请注意,这只是可能发生的许多事情之一,因为访问已被破坏的 object 是未定义的行为。

Instead, consider doing this:相反,请考虑这样做:

void Node::clear() {
  cout << "Clear: " << this << ":" << value << endl;
  if(next != NULL){
    next -> clear();
    delete next;
    next = NULL;
  }
}

Even better, do this in Node's destructor, and then you can just delete the target node:更好的是,在 Node 的析构函数中执行此操作,然后您可以删除目标节点:

void Node::~Node() {
  clear();
}

void Node::clear() {
  cout << "Clear: " << this << ":" << value << endl;
  if(next != NULL){
    delete next;
    next = NULL;
  }
}

Even better, make next a std::unique_ptr and then you can just reset it on clear() , destruction is automatic, and copying a Node is properly forbidden:更好的是,制作next一个std::unique_ptr ,然后您可以在clear()上重置它,销毁是自动的,并且正确禁止复制节点:

class Node {
private:
  std::unique_ptr<Node> next;
  double value;
public:
  void clear();
};

void Node::clear() {
  cout << "Clear: " << this << ":" << value << endl;
  next.reset(null);
}

Note that the last node (the head) cannot remove itself.请注意,最后一个节点(头部)不能自行移除。 As others have noted, clearing a node can't reasonably do anything except stop pointing at the next node.正如其他人所指出的,清除一个节点除了停止指向下一个节点之外,不能合理地做任何事情。 You need to have a separate class for a list, and clear that.您需要有一个单独的 class 列表,并清除它。

Everything after your clear() is undefined behavior as your variable head has been deleted in the clear function. clear()之后的所有内容都是未定义的行为,因为您的变量head已在clear function 中删除。 You can just consider your print after that garbage.你可以在垃圾之后考虑你的打印。

As for a proper way of freeing everything, you should put your clear function outside of your Node struct:至于释放一切的正确方法,您应该将清晰的 function 放在Node结构之外:

void clear(Node* head)
{
  Node* next = head->next;
  delete head;
  if (next != nullptr)
    clear(next);
}

I think calling delete in the destructor is UB as delete calls the destructor for you.我认为在析构函数中调用 delete 是 UB,因为 delete 会为你调用析构函数。 As mentionned in the comments, the delete is not present in the destructor, forget what I said!正如评论中提到的,析构函数中不存在delete ,忘记我说的!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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