[英]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.