C++模板链接列表出现问题



我以前做过一些链表,这些概念对我来说都很有意义,但对于一个项目,我必须用C++做一个模板化的链表,我没有用太多,我遇到了一些麻烦。请帮忙。我在这么简单的事情上花了太多时间。

我已经有了一些列表类,但问题就在这里。当我在一个测试用例中创建三个节点并将它们全部连接起来时,如果我调用

node1.getNext().show();

这很好,但如果我

node1.getNext().getNext().show();

我得到了一个segfault(核心转储)。这里怎么了?我已经尝试过多次更改getNext()和getPrevi()返回值上的指针,但都没有成功。问这个问题我觉得很愚蠢,但我遇到了一些严重的麻烦。下面是我的节点类,后面是一个给出segfault的示例测试用例。

节点.h:

template <class T> class Node
{
 public:
  Node();
  Node(T value);
  void setPrev(Node<T> node);
  void setValue(T value);
  void setNext(Node<T> node);
  Node<T> getPrev();
  T getValue();
  Node<T> getNext();
  void show();
  ~Node() { }
 private:
  Node<T> *prev;
  Node<T> *next;
  T value;
};
//default construct                                                                                                                                                     
template <class T> Node<T>::Node() {
  this->prev = NULL;
  this->value = NULL;
  this->next = NULL;
};
//overloaded construct                                                                                                                                                  
template <class T> Node<T>::Node(T value) {
  this->prev = NULL;
  this->value = value;
  this->next = NULL;
}
template <class T> void Node<T>::setPrev(Node<T> node) {
  this->prev = &node;
}
template <class T> void Node<T>::setValue(T value) {
  this->value = value;
}
template <class T> void Node<T>::setNext(Node<T> node) {
  this->next = &node;
}
template <class T> Node<T> Node<T>::getPrev() {
  return this->prev;
}
template <class T> T Node<T>::getValue() {
  return this->value;
}
template <class T> Node<T> Node<T>::getNext() {
  return this->next;
}
template <class T>
void Node<T>::show() {
  cout << value << endl;
}

测试用例:

int main(int argc, char **argv) {
  typedef Node<int> IntNode;
  IntNode head(NULL);
  IntNode node1(23);
  IntNode node2(45);
  IntNode node3(77);
  IntNode tail(NULL);
  node1.setPrev(head);
  node1.setNext(node2);
  node2.setPrev(node1);
  node2.setNext(node3);
  node3.setPrev(node2);
  node3.setNext(tail);
  node1.show();
  node2.show();
  node3.show();
  cout << node1.getNext().getValue() << endl;
  cout << node1.getNext().getNext().getValue() << endl;
}

您需要通过引用而不是通过值传递值。

当执行node1.setNext(node1)时,setNext()在堆栈上获得node1的副本,而不是您在main()中定义的变量。一旦setNext()退出,存储在next中的地址将不再有效。

对于初学者,将函数setPrevi和setNext重新定义为

template <class T> void Node<T>::setPrev(Node<T> &node) {
  this->prev = &node;
}
template <class T> void Node<T>::setNext(Node<T> &node) {
  this->next = &node;
}

这将修复您的即时segfault。然而,您确实需要更多地考虑代码的设计,以及当您通过引用或值传递时会发生什么,以正确地编写代码并避免进一步的问题。

您应该将下一个/上一个成员存储为指针。设置上一个和下一个节点时,将按值获取参数,从而进行复制。

这意味着,当您进入node1.getNext().getNext().getValue()中的第二个.getNext()时,您将遇到一个悬空指针,这就是代码失败的原因。

手动添加节点是很费力的,类似std::list的工作方式是使用指向其拥有的集合的beginend指针。当一个新节点被推到列表的前面或后面时,集合会创建节点,存储值并链接指针,为下一个节点和/或遍历做好准备。

最大的问题是setNextsetPrev函数按值获取参数,因此您将获得在main中声明的节点的副本

如果要继续执行此操作,请通过引用或指针传递这些参数。传递指针可能会更有语义,并防止这种意外的错误。

相关内容

  • 没有找到相关文章