有人可以运行此代码,并告诉我为什么insert中的节点不断被覆盖吗?
#ifndef LinkedList_hpp
#define LinkedList_hpp
#include <stdio.h>
#include <utility>
template<class T>class LinkedList{
public:
LinkedList(){
head = nullptr;
tail = nullptr;
size = 0;
}
//void insert(T val);
class Node{
public:
Node* next;
T* value;
Node* prev;
Node(T* value){
this->value = value;
}
Node(){
}
Node(T* value,Node* prev, Node* next){
this->value = value;
this->next = next;
this->prev = prev;
}
Node* operator=(const Node& node){
this->value = node.value;
this->prev = node.prev;
this->next = node.next;
return *this;
}
};
public:
Node* head;
Node* tail;
int size;
void insert(T val){
在此行,如果先前的head为10,则当前val为40,它将覆盖旧的head值,并插入一个新的值为val 40的节点。
Node* temp = new Node(&val);
if(head==nullptr){
head = temp;
tail = temp;
}else{
temp->next = head;
head->prev = temp;
head = temp;
}
size++;
}
#endif
#include <iostream>
#include "LinkedList.hpp"
int main(int argc, const char * argv[]) {
// LinkedList<int> t;
int h = 7;
int j = 10;
int k = 40;
LinkedList<int>* list1 = new LinkedList<int>();
list1->insert(h);
list1->insert(j);
list1->insert(k);
return 0;
}
每次调用insert并构造一个新节点时,它将覆盖旧值,并且所有内容都将成为当前Val
答案 0 :(得分:2)
void insert(T val){
val
是此函数的参数。此对象val
仅在该函数返回之前存在。到那时它会被破坏,就像在函数内部的非静态范围内声明的所有其他项一样。这就是C ++的工作方式。 insert()
返回后,将不再val
。它不再存在。它去见其制造商。它变成了一个不存在的对象,不再存在并且完全是过去。
您的insert()
函数执行以下操作:
Node* temp = new Node(&val);
您要将指向此val
参数的指针传递给Node
的构造函数,然后Node
将指向该参数的指针保存为insert()
,作为其自己的指针班级成员。
那太好了,但是一旦insert()
返回,在new
-ed Node
中保存的指针将成为指向销毁对象的指针,而取消引用该指针将成为未定义的行为。
然后,您稍后尝试取消对原始指针的引用,该指针不再指向有效对象。
这说明了在代码中观察到的未定义行为。
最重要的是,您的类和模板的设计从根本上来说是有缺陷的。 Node
使用指针没有明显目的。 Node
应该简单地将T
作为自己的类成员和value
存储,而不是将value
指向某个地方存在的其他T
的指针,并且可以随时被摧毁,不受Node
的控制。
所示代码中的另一个问题是Node
的两个构造函数无法初始化next
的{{1}}和prev
指针。这也会导致不确定的行为。
答案 1 :(得分:1)
<form id="form">
<input type="number" min="8" name="number" />
<input type="submit" value="submit">
</form>
<script>
var number = 0;
var $form = $("#form");
var $input = $form.find("input[name=number]");
$form.submit(function(e){
e.preventDefault();
number = +($input.val());
});
</script>
按值接受参数,因此void insert(T val)
是本地副本,而不是原始副本。
val
存储一个指向此本地副本的指针。该副本超出范围,因此在插入退出后您正在查看的是内存中已存在的伪影,该伪影不再有效。在这种情况下,鬼影似乎总是保留最后设置的值。
灵巧的方式:直接存储Node* temp = new Node(&val);
而不是将其与节点保持连接所需的指针。这种方式的内存管理要少得多。
Node::value
成为
T* value;
和
T value;
成为
Node(T* value){
this->value = value;
}
Node(T value){
this->value = value;
}
的其他用途必须相应更新。通常,value
令人头疼,it should be used sparingly。
愚蠢的方式:通过引用传递
new
,以便指针指向寿命更长的原稿。