在C ++中为双链表实现自定义Iterator和const_iterator

时间:2018-12-13 22:33:53

标签: c++ data-structures linked-list operator-overloading doubly-linked-list

这是我对双链表的iteratorconst_iterator的实现。程序具有强制性测试。当我运行程序时,我从测试中得到错误:

  

“减量运算符将迭代器向后移动,前缀”,原因是   致命错误情况:SIGSEGV-细分违规信号

我在做什么错?

test.cpp //这是我得到错误///

的测试文件
TEST_CASE("Decrement operator moves the iterator backward", "[stage2]") {
    list l;
    append_to_list(l, { 5.55, 6.66, 7.77, 8.88 });

    auto it = l.end();
    SECTION("Prefix") {
        REQUIRE(*(--it) == 8.88);
        REQUIRE(*(--it) == 7.77);
        REQUIRE(*(--it) == 6.66);
        REQUIRE(*(--it) == 5.55);
        REQUIRE(it == l.begin());
    }

    SECTION("Postfix") {
        it--;
        REQUIRE(*(it--) == 8.88);
        REQUIRE(*(it--) == 7.77);
        REQUIRE(*(it--) == 6.66);
        REQUIRE(*it == 5.55);
        REQUIRE(it == l.begin());
    }
}

TEST_CASE("Decrement operator moves the (const) iterator backward", "[stage2]") {
    list l;
    append_to_list(l, { 5.55, 6.66, 7.77, 8.88 });

    auto it = l.cend();
    SECTION("Prefix") {
        REQUIRE(*(--it) == 8.88);
        REQUIRE(*(--it) == 7.77);
        REQUIRE(*(--it) == 6.66);
        REQUIRE(*(--it) == 5.55);
        REQUIRE(it == l.cbegin());
    }

    SECTION("Postfix") {
        it--;
        REQUIRE(*(it--) == 8.88);
        REQUIRE(*(it--) == 7.77);
        REQUIRE(*(it--) == 6.66);
        REQUIRE(*it == 5.55);
        REQUIRE(it == l.cbegin());
    }
}

list.hpp

class list {
private:
    struct node {
        double val = 0;
        node* prev = nullptr;
        node* next = nullptr;
    };

    node* head = nullptr;
    node* tail = nullptr;
    size_t num_elements = 0;

public:

    class const_iterator {
        node* current_ptr = nullptr;
        const list* o_list = nullptr;
    public:
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::bidirectional_iterator_tag;
        using value_type = const double;
        using reference = const double&;
        using pointer = const double*;

        const_iterator() = default;
        const_iterator(node* ptr, const list* gen);

        const_iterator& operator++();
        const_iterator operator++(int);
        const_iterator& operator--();
        const_iterator operator--(int);

        reference operator*() const;
        pointer operator->() const;

        bool operator==(const const_iterator& rhs) const;
        bool operator!=(const const_iterator& rhs) const;

        friend class list;
    };

    class iterator {
        node* current_ptr = nullptr;
        const list* o_list = nullptr;
    public:
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::bidirectional_iterator_tag;
        using value_type = double;
        using reference = double&;
        using pointer = double*;

        iterator() = default;
        iterator(node* ptr, const list* gen);

        iterator& operator++();
        iterator operator++(int);
        iterator& operator--();
        iterator operator--(int);

        reference operator*() const;
        pointer operator->() const;

        operator const_iterator() const;

        bool operator==(const iterator& rhs) const;
        bool operator!=(const iterator& rhs) const;

        friend class list;
    };

list.cpp //我对迭代器和const_iterator的实现//

list::iterator list::begin() {
        return list::iterator(head, this);
    }

    list::iterator list::end() {
        return list::iterator(tail->next, this);
    }

    list::const_iterator list::begin() const {
        return list::const_iterator(head, this);
    }

    list::const_iterator list::end() const {
        return list::const_iterator(tail->next, this);
    }

    list::const_iterator list::cbegin() const {
        return list::const_iterator(head, this);
    }

    list::const_iterator list::cend() const {
        return list::const_iterator(tail->next, this);
    }

    list::iterator::iterator(node *ptr, const list *gen) {
        this->current_ptr = ptr;
        this->o_list = gen;
    }

    list::iterator& list::iterator::operator++() {
        current_ptr = this->current_ptr->next;
        return *this;
    }

    list::iterator& list::iterator::operator--() { //here triggers error!!!
        current_ptr = this->current_ptr->prev;
        return *this;
    }

    list::iterator list::iterator::operator++(int)
    {
        iterator old(*this);
        ++(*this);
        return old;
    }

    list::iterator list::iterator::operator--(int)
    {
        iterator left(*this);
        --(*this);
        return left;
    }
    list::const_iterator& list::const_iterator::operator++() {
        current_ptr = current_ptr->next;
        return *this;
    }

    list::const_iterator& list::const_iterator::operator--() { //here triggers error!!!
        current_ptr = current_ptr->prev;
        return *this;
    }

    list::const_iterator list::const_iterator::operator++(int) {
        const_iterator old = *this;
        ++(*this);
        return old;
    }

    list::const_iterator list::const_iterator::operator--(int) {
        const_iterator old = *(this);
        --(*this);
        return old;
    }

1 个答案:

答案 0 :(得分:1)

问题是您使用空node *作为您的end(),它无法与operator--一起使用;没有办法减少它到达列表的最后一个节点。

您需要使用其他内容作为结束标记,以使您可以返回列表-列表中的假“节点”不是真实列表的元素,或者添加指向该列表的指针迭代器类的原始列表,因此当减少end()迭代器时,您可以恢复列表中的最后一个节点。


由于您的迭代器已经具有一个o_list指针,因此最简单的方法就是使用它:

list::iterator& list::iterator::operator--() {
    current_ptr = current_ptr ? current_ptr->prev : o_list->tail;
    return *this;
}