如何从shared_ptr向量中的某个位置移除对象并推回到末尾

How to remove an object from a position in a vector of shared_ptr and push back to the end?

本文关键字:对象 位置 shared ptr 向量      更新时间:2023-10-16

我想创建一个方法,在vector中搜索特定对象(本例为Bar对象)。当我在vector中找到那个对象条时,我应该把push_back那块放到vector的末尾。

关于这个实施,我有三个问题。。。但我不知道是否有更简单的方法。

这是我的实现:

std::vector<std::shared_ptr<Bar>> mBarVector;
//(...)
void Foo::pushBack(Bar& bar)
{
    for (auto& b : mBarVector)
    {
        if(*b == bar) // ERROR [1]
        {
            //mBarVector.erase(?) This position...?! How? [2]
            //mBarVector.push_back(bar); ERROR! [3]
        }
    }
}
  1. 如何将条向量上的当前迭代与方法参数中对条的引用进行比较?

  2. 既然我不使用for(int I=0,…),我该如何擦除我当前所在的位置?

  3. 从向量中删除bar对象后,如何插入来自引用(到shared_ptr)的新对象?

  1. 如果你想做一个深入的比较,那么你现在做得很正确,但你需要实现operator==(const Bar&, const Bar&)。如果你想做一个浅层次的比较,那么你需要比较对象的地址:if(b.get() == &bar)

  2. 除非单独跟踪索引或其他迭代器,否则不能在基于范围的循环中擦除当前项。在这种情况下,基于范围的循环根本没有用处。

  3. 指向该对象的共享指针位于变量b中。只需复制即可。或者,为了更好的性能,移动它。

但我不知道是否有更简单的方法。

有。

首先,您需要为要移动的元素找到一个迭代器。要做到这一点,最简单的方法再次取决于你是想进行肤浅的比较还是深入的比较。为了进行深入比较,可以使用std::find。您仍然需要定义operator==(const Bar&, const Bar&)。对于浅层比较,可以将std::find_if与比较地址的比较函数一起使用。

一旦有了迭代器,如果希望其他元素的顺序保持不变,就可以使用std::rotate将指向的元素移动到末尾。只需将向量从找到的元素旋转到末尾,即可使下一个元素成为第一个元素。或者,如果顺序在其他方面不相关,那么您可以使用最后一个元素执行std::swap,这更有效。

编辑:mkaes在评论中提出std::stable_partition。它也可以工作,不需要单独的find调用。即使使用深度比较,也需要一个比较函子。它也适用于多场比赛,但这也意味着如果找到一场比赛,它不会提前结束。如果其他元素的顺序不可逆,则可以使用std::partition