3

我当前的家庭作业让我为列表创建一个迭代器类。我坚持创建一个好的erase(iterator where)功能。

当前代码(简化为适合问题):

class List
{
    class _Iter
    {
        friend class List;
    public:
        _Iter(ListElem *pCurr, List *pList);

        /* *, ->, ++, --, == and != operators overloaded */

    private:
        ListElem *pCurr_; List *pList_;
    };

    typedef _Iter iterator;

    iterator erase(iterator where);
};

像这样实现擦除:

// Precondition: List has been checked for size > 0.
List::iterator List::erase(List::iterator& where)
{
    // Erasing only element in list.
    if(where == end() && where == begin())
    {
        pop_back(); // or pop_front();
        return iterator(0, this);
    }

    // Elem at end
    if(where == end())
    {
        pop_back();
        return end();
    }
    else 
    {
        // Elem at beginning
        if(where == begin())
        {
            pop_front();
            return ++begin();
        }
    }

    // Elem somewhere between beginning and end.
    iterator temp(where);
    // The node next to pCurr_ should point to the one before pCurr_
    where.pCurr_->next->prev = where.pCurr_->prev;
    // The node before pCurr_ should point to the one after pCurr_
    where.pCurr_->prev->next = where.pCurr_->next;
    // Return the node after pCurr_
    ++temp;
    delete where.pCurr_;
    --size_;
    return temp;
} 

前三种情况——只有元素、结束元素和开始元素——都可以。_Iter编码很好,绝对不需要任何知识和对s 成员的私人访问。但是,如果元素不在这些位置,那么我(似乎)别无选择,只能违反封装并直接更改 pCurr_ (列表的元素)。

有没有办法避免这种情况?我查看了 STL 列表,但他们使用了一些其他功能_Next_Node_(/* stuff */)_Prev_Node_(/* stuff */)这对我来说不是很有用。谷歌搜索给了我关于如何使用擦除功能的有用结果,而不是如何自己编写。

问题:有没有一种方法可以擦除迭代器指向的元素,而不必抓取它的 pCurr_ 成员?

4

2 回答 2

3
  1. 不要使用以下划线开头后跟大写字母的标识符。它们是为标准库和系统编写者保留的。尽管您正在编写自己的列表类,但实际上并不是在编写标准库。

  2. end() 通常是列表末尾之后的一个元素,而不是最后一个元素。(要获得列表的实际最后一个迭代器,您可以在发生时执行 l.rbegin().base() )。

  3. 按值传递迭代器,而不是非常量引用。

  4. 为什么你如此关心修改 pCurr?

于 2010-12-20T14:34:34.383 回答
2

这并没有真正违反封装。容器和它的迭代器紧密耦合几乎是不可避免的。他们两个一起向用户隐藏了实现细节。如果他们不是彼此的朋友,更多的实现细节将不得不泄露给用户。如果所讨论的类有充分的理由了解彼此的内部结构,friend关键字可以增强封装。

请注意,begin() == end()用一个元素表示列表不是标准库约定,这意味着容器为空。end()应该将迭代器返回到容器的“one-past-the-end”。

于 2010-12-20T14:39:47.110 回答