使用迭代器擦除容器元素

时间:2010-12-20 14:24:02

标签: c++ iterator erase

我目前的家庭作业让我为列表创建一个迭代器类。我坚持创造一个好的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成员的知识和私人访问权限。但是,如果元素不在那些位置,那么我(似乎)别无选择,只能违反封装并直接更改pCurr_(列表元素)。

有什么方法可以避免这种情况吗?我查看了STL列表,但他们使用了一些对我来说不是很有用的其他函数_Next_Node_(/* stuff */)_Prev_Node_(/* stuff */)。谷歌搜索为我提供了有关如何使用擦除功能的有用结果,而不是如何自己编写。

问题:有没有办法可以擦除迭代器指向的元素而不必抓住它的pCurr_成员?

2 个答案:

答案 0 :(得分:3)

  1. 请勿使用以下划线开头,后跟大写字母的标识符。它们保留给标准库和系统编写器。虽然您正在编写自己的列表类,但实际上并没有编写标准库。

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

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

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

答案 1 :(得分:2)

这并没有真正违反封装。容器及其迭代器紧密耦合几乎是不可避免的。他们两个一起隐藏了用户的实现细节。如果他们不是彼此的朋友,则必须将更多实施细节泄露给用户。 朋友关键字可以增强封装,如果相关课程有正当理由了解彼此的内部结构。

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