【问题标题】:Overloading prefix increment operator for iterator class throws segmentation fault重载迭代器类的前缀增量运算符会引发分段错误
【发布时间】:2020-10-14 05:43:20
【问题描述】:

当迭代器到达链表类中的最后一个节点时,我遇到了分段错误。 通过调试可以看到,当迭代器到达链表的末尾时,node->next_ 指向 null 从而抛出了 seg 错误。

编辑:

我已经包含了void push_front() 方法的定义

列表.h

    void push_front(const T& value) {
        
        Node* node = new Node(value, nullptr, nullptr);

        if (head_ == nullptr) {
            head_ = node;
            tail_ = head_;
        }
        else {
            node->next_ = head_;
            head_ = node;
        }
    }

我尝试将重载的运算符更改为以下,但没有成功:

iterator& operator++() {
    iNode = iNode->next_;  //this line throws the exception
    return *this;
}

//and

iterator& operator++() {
    return ++(*this);
}

非常感谢任何帮助!

main.cpp

#include <iostream>
#include "List.h"
#include <string>

int main(){

    List<int> l1;

    l1.push_front(4);
    l1.push_front(3);
    l1.push_front(2);
    l1.push_front(1);
    l1.push_front(0);


    for (auto i = l1.begin(); i != l1.end(); ++i)
    {
        int j = 0;  
    }

    l1.printList();
}



列表.h

template<typename T>
class List
{
public:

    class Node {
    public:

        Node(T value, Node* prev, Node* next) : value_(value), prev_(prev), next_(next) {}

        T value_;
        Node* next_;
        Node* prev_;
    };

    Node* head_;
    Node* tail_;

    //! An iterator over the list
    class iterator
    {
    public:

        Node* iNode;
        iterator(Node* head): iNode(head){ }
        ~iterator() {}

        T& operator*() {
            return  iNode -> value_;
        }
    
        //prefix increment
        iterator& operator++() {
            this->iNode = this->iNode->next_;  //this line throws the exception
            return *this;

        }
           
        //postfix increment
        iterator operator++(int ignored) {
            iterator result = *this; 
            ++(*this); 
            return result;
        }

        bool operator== (const iterator& it) const {
            return iNode == it.iNode;
        }

        bool operator!= (const iterator& it) const {
            return !(iNode == it.iNode);
        }
     };

//! Get an iterator to the beginning of the list
    iterator begin() {
        return List<T>::iterator(head_);
    }

    //! Get an iterator just past the end of the list
    iterator end() {
        return List<T>::iterator(nullptr);
    }
};

【问题讨论】:

  • push_back的定义在哪里?可能链表本身已损坏。
  • iterator&amp; operator++() { return ++(*this); } 导致未定义的行为(无限递归)
  • @cigien 我已经包含了push_front()的定义
  • 添加operator!=并注释掉l1.printList();后无法重现:coliru.stacked-crooked.com/a/5e04329a7284f721请提供minimal reproducible example
  • 你永远不会使用prev_ 成员(即使你push_front 你仍然离开它nullptr)。

标签: c++ linked-list operator-overloading


【解决方案1】:

需要将head_默认初始化为nullptr

Node* head_ = nullptr;

否则head_ 有一些不确定的值,并且不能保证push_front 中的以下检查有效:

if (head_ == nullptr)

即使head_ 没有指向有效内存。

请注意,即使您从未调用过push_front,也会出现此问题,因为在for 循环中检查begin 迭代器的iNode 可能不是nullptr,即使列表为空。这意味着i会递增,这会导致访问next_operator++中出现UB。

这是demo。 (如果不初始化head_,程序会出现段错误。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    • 2012-01-05
    • 2012-03-12
    • 2011-03-12
    • 1970-01-01
    相关资源
    最近更新 更多