You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带自定义迭代器的双向链表类型转换错误排查求助

双向链表自定义迭代器类型转换错误修复方案

作为编程练习,尝试实现带有自定义迭代器的双向链表,测试时出现大量类型转换错误,代码及编译错误如下:

原实现代码

template<typename Type>
class UnorderedList 
{
    private:
        int listsize;
        struct Node {
            Type data;
            Node * next;
            Node * previous;
            Node() {
                next = previous = nullptr;
                data = Type();
            }
        };
        Node * first;
        Node * last;
        Node * end_place; // empty node for end() function, not to be used or dereferenced
    public:
        // iterators
        class iterator {
            private:
                // internal iterator pointer
                Node * n_ptr;
            public:
                // iterator tags for compiler
                using iterator_category = std::bidirectional_iterator_tag;
                using difference_type   = std::ptrdiff_t;
                using value_type        = Node;
                using pointer           = Node *;
                using reference         = Node &;
                
                // iterator constructor
                iterator(Node * node) { n_ptr = node; }
                
                // iterator operator overloads for bidirectional_iterator
                reference operator * () { return n_ptr; }
                pointer operator -> () { return n_ptr; }
                iterator & operator ++ () { n_ptr = n_ptr -> next; return * this; }
                iterator operator ++ (int) { iterator temp = * this; ++(* this); return temp; }
                iterator & operator -- () { n_ptr = n_ptr -> previous; return * this; }
                iterator operator -- (int) { iterator temp = * this; --(* this); return temp; }
                friend bool operator == (const iterator & a, const iterator & b) { return (a.n_ptr == b.n_ptr); }
                friend bool operator != (const iterator & a, const iterator & b) { return (a.n_ptr != b.n_ptr); }
        };

        // begin() and end() returning iterators
        iterator begin() { return iterator(first); }
        iterator end() { return iterator(end_place); }
    
        // list constructors
        UnorderedList(int size) {
            Node * one = nullptr;
            Node * two = nullptr;
            two = new Node;
            two -> previous = one;
            first = two;
            for (int i = 1; i < size; ++i) {
                two = new Node;
                one -> next = two;
                two -> previous = one;
            }
            last = two;
            end_place = new Node;
            end_place -> data = NULL;
            end_place -> previous = end_place -> next = nullptr;
            last -> next = end_place;
            listsize = size;
        }
        UnorderedList(int size, Type fill) {
            Node * one = nullptr;
            Node * two = nullptr;
            two = new Node;
            two -> previous = one;
            two -> data = fill;
            first = two;
            one = two;
            for (int i = 1; i < size; ++i) {
                two = new Node;
                two -> data = fill;
                one -> next = two;
                two -> previous = one;
            }
            last = two;
            end_place = new Node;
            end_place -> data = Type();
            end_place -> previous = end_place -> next = nullptr;
            last -> next = end_place;
            listsize = size;
        }
        UnorderedList(int size, Type * values) {
            Node * one = nullptr;
            Node * two = nullptr;
            two = new Node;
            two -> previous = one;
            two -> data = * values;
            first = two;
            for (int i = 1; i < size; ++i) {
                two = new Node;
                two -> data = * (values + i);
                one -> next = two;
                two -> previous = one;
            }
            last = two;
            end_place = new Node;
            end_place -> data = NULL;
            end_place -> previous = end_place -> next = nullptr;
            last -> next = end_place;
            listsize = size;
        }

        // member functions
        // return size of list; O(1)
        int size() { return listsize; }
        // return true if list is empty, false otherwise; O(1)
        bool empty() { return (listsize == 0); }
        // returns an iterator pointing to the node at the desired position; O(n)
        iterator get(int position) {
            if (position < listsize / 2) {
                // the position is in the first half of the list
                iterator it = begin();
                for (int i = 0; i < position; ++i) ++it;
                return it;
            }
            // the position is in the second half of the list
            iterator it(last);
            for (int i = 0; i < listsize - position - 1; ++i) --it;
            return it;
        }
        // edit the value of the node pointed to by the iterator; O(1)
        void edit(iterator it, Type value) {
            Node * node = * it;
            node -> data = value;
        }
        // push a new node to the front of the list; O(1)
        void push_front(Type value) {
            Node * newfront = new Node;
            newfront -> data = value;
            newfront -> next = first;
            first -> previous = newfront;
            newfront -> previous = nullptr;
            first = newfront;
            ++listsize;
        }
        // pop the front of the list if it is not empty, strong exception guarantee; O(1)
        void pop_front() {
            if (listsize == 0) {
                std::cerr << "Cannot pop empty list\n";
                return;
            }
            if (listsize == 1) {
                delete first;
                return;
            }
            Node * newfirst = first -> next;
            delete first;
            first = newfirst;
            first -> previous = nullptr;
            --listsize;
        }
        // push a new node to the back of the list; O(1)
        void push_back(Type value) {
            Node * newback = new Node;
            newback -> data = value;
            newback -> previous = last;
            last -> next = newback;
            newback -> next = end_place;
            last = newback;
            ++listsize;
        }
        // pop the back of the list if it is not empty, strong exception guarantee; O(1)
        void pop_back() {
            if (listsize == 0) {
                std::cerr << "Cannot pop empty list\n";
                return;
            }
            if (listsize == 1) {
                delete first;
                return;
            }
            Node * newlast = last -> previous;
            delete last;
            last = newlast;
            last -> next = nullptr;
            --listsize;
        }
        // insert a new node before the node pointed to by the iterator; O(1)
        void insert(iterator it, Type value) {
            if (it == begin()) { push_front(value); return; }
            if (it == end()) { push_back(value); return; }
            Node * before = & (* (--it));
            ++it;
            Node * after = & (* (++it));
            Node * inserted = new Node;
            inserted -> data = value;
            before -> next = inserted;
            after -> previous = inserted;
            inserted -> next = after;
            inserted -> previous = before;
            ++listsize;
        }
        // pop the node pointed to by it, strong exception guarantee
        void pop(iterator it) {
            if (it == begin()) { pop_front(); return; }
            if (it == end()) { pop_back(); return; }
            if (listsize == 0) {
                std::cerr << "Cannot pop empty list\n";
                return;
            }
            if (listsize == 1) {
                delete first;
                return;
            }
            Node * before = * (--it);
            ++it;
            Node * after = * (++it);
            before -> next = after;
            after -> previous = before;
            Node * deletenode = * it;
            delete deletenode;
        }
        void reverse(iterator from, iterator to) {
            if (from == to) return;
            vector<Type> v;
            int cnt = 0;
            for (iterator it = from, end = to; it != end; ++it) 
            {
                Node * curr = * it;
                v.push_back(curr.data);
                ++cnt;
            }
            std::reverse(v.begin(), v.end());
        }
        void reverse() {
            reverse(begin(), end());
        }
        UnorderedList operator + (UnorderedList & nextlist) {
            delete end_place;
            last -> next = nextlist.first;
            nextlist.first -> previous = last;
            return * this;
        }
        ~ UnorderedList () {
            Node * current = first;
            Node * next = current -> next;
            for (int i = 0; i < listsize; ++i) {
                delete current;
                current = next;
                next = current -> next;
            }
            delete first;
            delete last;
            delete end_place;
        }

        void display() {
            for (iterator it = begin(), eit = end(); it != eit; ++it) {
                Node * node = * it;
                cout << node -> data << (it == --eit ? "\n" : " <=> ");
            }
        }
};

编译错误输出

*  Executing task: C/C++: g++ build active file 

Starting build...
/usr/bin/g++ -fdiagnostics-color=always -g /Users/ericssonlin/code/C++/template.cpp -o /Users/ericssonlin/code/C++/template
/Users/ericssonlin/code/C++/template.cpp:43:43: 警告:别名声明是C++11扩展特性 [-Wc++11-extensions]
                using iterator_category = std::bidirectional_iterator_tag;
                                          ^
/Users/ericssonlin/code/C++/template.cpp:44:43: 警告:别名声明是C++11扩展特性 [-Wc++11-extensions]
                using difference_type   = std::ptrdiff_t;
                                          ^
/Users/ericssonlin/code/C++/template.cpp:45:43: 警告:别名声明是C++11扩展特性 [-Wc++11-extensions]
                using value_type        = Node;
                                          ^
/Users/ericssonlin/code/C++/template.cpp:46:43: 警告:别名声明是C++11扩展特性 [-Wc++11-extensions]
                using pointer           = Node *;
                                          ^
/Users/ericssonlin/code/C++/template.cpp:47:43: 警告:别名声明是C++11扩展特性 [-Wc++11-extensions]
                using reference         = Node &;
                                          ^
/Users/ericssonlin/code/C++/template.cpp:245:33: 错误:成员引用的基类型'UnorderedList::Node *'不是结构体或联合体
                v.push_back(curr.data);
                            ~~~~^~~~~
/Users/ericssonlin/code/C++/template.cpp:274:24: 错误:无法将'UnorderedList<int>::Node'类型转换为'UnorderedList<int>::Node *'类型
                Node * node = * it;
                       ^      ~~~~
/Users/ericssonlin/code/C++/template.cpp:284:10: 注:在实例化成员函数'UnorderedList<int>::display'时请求
    list.display();
         ^
/Users/ericssonlin/code/C++/template.cpp:53:50: 错误:无法将无关类型'UnorderedList<int>::Node *'绑定到'UnorderedList<int>::Node'的非const左值引用
                reference operator * () { return n_ptr; }
                                                 ^~~~~
/Users/ericssonlin/code/C++/template.cpp:274:31: 注:在实例化成员函数'UnorderedList<int>::iterator::operator*'时请求
                Node * node = * it;
                              ^
/Users/ericssonlin/code/C++/template.cpp:284:10: 注:在实例化成员函数'UnorderedList<int>::display'时请求
    list.display();
         ^
/Users/ericssonlin/code/C++/template.cpp:244:24: 错误:无法将'UnorderedList<int>::Node'类型转换为'UnorderedList<int>::Node *'类型
                Node * curr = * it;
                       ^      ~~~~
/Users/ericssonlin/code/C++/template.cpp:251:13: 注:在实例化成员函数'UnorderedList<int>::reverse'时请求
            reverse(begin(), end());
            ^
/Users/ericssonlin/code/C++/template.cpp:290:10: 注:在实例化成员函数'UnorderedList<int>::reverse'时请求
    list.reverse();
         ^
/Users/ericssonlin/code/C++/template.cpp:230:20: 错误:无法将'UnorderedList<int>::Node'类型转换为'UnorderedList<int>::Node *'类型
            Node * before = * (--it);
                   ^        ~~~~~~~~
/Users/ericssonlin/code/C++/template.cpp:294:10: 注:在实例化成员函数'UnorderedList<int>::pop'时请求
    list.pop(it);
         ^
/Users/ericssonlin/code/C++/template.cpp:232:20: 错误:无法将'UnorderedList<int>::Node'类型转换为'UnorderedList<int>::Node *'类型
            Node * after = * (++it);
                   ^       ~~~~~~~~
/Users/ericssonlin/code/C++/template.cpp:235:20: 错误:无法将'UnorderedList<int>::Node'类型转换为'UnorderedList<int>::Node *'类型
            Node * deletenode = * it;
                   ^            ~~~~
生成5个警告和7个错误。

Build finished with error(s).

 *  The terminal process failed to launch (exit code: -1). 
 *  Terminal will be reused by tasks, press any key to close it. 

错误修复方案

1. 修正迭代器operator*的返回类型

迭代器的reference定义为Node&,但原代码返回的是Node*(n_ptr),类型不匹配,导致后续解引用迭代器得到Node对象,无法直接赋值给Node*变量。
修改operator*实现:

reference operator * () { return *n_ptr; }

2. 修正迭代器解引用的使用方式

所有试图将*it直接赋值给Node*的代码,需要改为取引用的地址:

  • display函数:Node * node = &(*it);
  • reverse函数:Node * curr = &(*it);
  • pop函数:Node * before = &(*(--it));、Node * after = &(*(++it));、Node * deletenode = &(*it);

3. 修正指针成员访问语法

curr是Node*类型,访问成员必须用->而非.:

v.push_back(curr->data);

4. 解决C++11扩展警告

编译时添加-std=c++11或更高版本的编译选项(如-std=c++17),启用C++11及以上标准。

5. 修复其他潜在逻辑错误

  • 构造函数空指针访问:UnorderedList(int size)中初始one为nullptr,循环中会触发空指针访问,重构构造逻辑:
UnorderedList(int size) {
    listsize = size;
    if (size == 0) {
        first = last = nullptr;
        end_place = new Node;
        return;
    }
    first = new Node;
    Node* prev = first;
    for (int i = 1; i < size; ++i) {
        Node* curr = new Node;
        prev->next = curr;
        curr->previous = prev;
        prev = curr;
    }
    last = prev;
    end_place = new Node;
    last->next = end_place;
    end_place->previous = last;
}
  • 析构函数重复删除:原析构函数重复删除first、last,且空列表时会触发空指针,重构析构:
~UnorderedList() {
    Node* current = first;
    while (current != end_place) {
        Node* next = current->next;
        delete current;
        current = next;
    }
    delete end_place;
}
  • operator+逻辑错误:原实现会修改当前对象并删除end_place,导致
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 13:19:09