2

假设我有一个单链表 alike std::forward_list。我想找到与谓词匹配的单个列表元素,对其执行一些操作,并可选择根据另一个谓词将其删除。

到目前为止,我已经组装了以下内容:

for (T::iterator it = l.begin(), prev_it = l.before_begin();
        it != l.end();)
{
    if (predicate)
    {
        // ...

        if (another_predicate)
        {
            l.erase_after(prev_it);
            break;
        }
    }

    prev_it = it;
    ++it;
}

但是,我特别想知道这是否是执行增量部分的最佳方式。或者,我一直在考虑:

    ++prev_it;
    ++it;

虽然在纯 C 中前者显然会更好,但在 C++ 中似乎不再那么清楚了。我相信使用更简单的迭代器,前者应该更简单;但是,如果复制迭代器可能涉及内存分配(例如,使用 PImpl 时),则后者实际上可能更好。

你认为哪种方法更好,为什么?请注意,我想避免将其严格限制为通用std::forward_list设计,并考虑一种适用于更复杂类型的解决方案。

4

2 回答 2

4

当 for 循环不增加它们的计数器时,我真的很困惑,所以我会简单地添加++prev_it, ++it到你的 for 循环中。您的迭代器将保持同步(前提是您不与它们混淆),并且名称清楚地说明了它们所指的内容。在担心性能之前,我总是在清晰度方面犯错。

您可能不应该担心将此代码推广到其他容器,因为这std::forward_list是一种特殊情况。其他容器不需要像erase_after.

于 2012-08-17T17:58:07.343 回答
2

如果你用两个增量而不是明显的先赋值后增量来编写它,那么所有未来的维护者都会盯着代码看一段时间,想知道它们缺少什么以及为什么以这种方式编写它。

您应该以明显的方式对其进行编码(保存 prev,然后递增),如果您的迭代器复制成本很高,而分析表明这是一个问题,请找到一个更好的迭代器。您通常不应该进行这样的代码更改来解决甚至可能不会明显影响您的性能的问题。

编辑:正如@Kerrek SB 在对该问题的评论中指出的那样,并且您对自己的意思稍微撒谎感到满意,您也可以使用forward_list::remove_if(小心)有状态的谓词来实现这一点。

于 2012-08-17T17:43:56.437 回答