【问题标题】:How can I move an element from a C++11 container to the back of the container?如何将元素从 C++11 容器移动到容器的背面?
【发布时间】:2015-01-09 03:29:04
【问题描述】:

如何将元素从 C++11 容器移动到容器的背面?

我专门使用列表,但如果需要可以使用向量(或者可能是任何容器;获得通用容器解决方案会很好)。

我有一个元素列表。我有一个价值。我将此值传递给每个元素;其中一个会回应。第一个响应的我想移到容器的后面。

我现有的代码如下所示:

std::list<elements> m_elements
...
bool handle(event e)
{
    for(auto &element : m_elements)
    {
        if(element->handle())
            return true;
    }
    return false;
}

但我现在想做的是将handle()s 事件的元素移动到m_elements 的末尾。对于一些上下文,我正在研究 Windows 的 GUI 系统。所以无论哪个窗口恰好捕捉到鼠标,在绘制的时候都需要跳转到顶部; m_elements 中的窗口正在被一个一个地绘制(所以最后一个元素在顶部)。

可能值得注意的是元素是std::shared_ptrs。

编辑

如果有人遇到此问题并回答类似情况。

我实际上需要通过我的容器向后迭代来处理输入,因为最后一个元素是最后绘制的,即它在顶部,所以它应该是第一个应该尝试拦截输入的元素。

这很简单。但是,将反向迭代器拼接到容器的末尾有点棘手。如果迭代器是前向迭代器,std::reverse_iterator.base() 将返回 NEXT 迭代器,因此您需要将迭代器 std::advance -1 以成功移动“拦截”的实际元素。

for(auto itr = m_elements.rbegin(); itr != m_elements.rend(); ++itr)
{
    if((*itr)->handle(e))
    {
        auto itr2 = itr.base();
        std::advance(itr2,-1);
        m_elements.splice(m_elements.end(), m_elements, itr2);
        return true;
    }
}

希望这能帮助下一个可怜的灵魂。

【问题讨论】:

  • 你尝试的时候发生了什么?
  • 为什么不直接交换它们呢?
  • 听起来你想用std::partition
  • 因为分区和交换对其他元素没有顺序保留

标签: c++ stl


【解决方案1】:

如果您想删除元素并将其添加到末尾(有效地将其他所有内容向下移动),那么您可以使用std::list::splice 方法执行此操作,该方法将在新位置重新链接节点,而无需任何节点被创建或销毁。它所要做的就是调整现有节点上的节点指针以反映您想要的更改。

for (auto i = m_elements.begin(); i != m_elements.end(); ++i) {
    if ((*i)->handle()) {
        // Move this node to the back.
        m_elements.splice(m_elements.end(), m_elements, i);

        return true;
    }
}

return false;

有更通用的解决方案适用于任何容器(包括std::list),但与特定容器的技术相比,它们可能不是最佳的。

【讨论】:

  • 会不会让集合失效,让for循环失败?
  • @Ajay 在m_elements.erase(i) 之后,i 迭代器确实无效,但没关系,因为我们之后立即返回。如果我们需要继续遍历数组,那么我们将不得不使用 i = m_elements.erase(i) 习语并将 ++i 移动到 else 块中,但既然我们不在,那就不用担心了。
  • 是的,这很有道理! :)
猜你喜欢
  • 1970-01-01
  • 2013-10-23
  • 2012-02-16
  • 2021-12-16
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多