从标准容器中移动元素是否合法?

Is it legal to move elements from standard containers?

我正在写一个class,它需要高效的函数来过滤成员容器(比方说std::vector)。此函数应具有类似于以下的界面:

void filter(std::vector<SomeType>& items, const std::vector<int>& inds);

该函数应使容器 items 处于以下状态: - 应删除 inds 中索引指向的项目 - 其他物品应留在容器中以保持初始顺序。

为简单起见,我们假设 inds 是一个完美的容器,每个操作的复杂度为 O(1),并且所有索引都有效且没有重复。

我的想法是创建第二个容器,保留所需的 space,然后移动(通过 std::move)每个未被 inds 索引的元素到这个新容器中;然后交换旧容器和新容器。

例如像这样:

void filter(std::vector<SomeType>& items, const std::vector<int>& inds)
{
    std::vector<SomeType> new_items{};
    new_items.reserve( items.size() - inds.size() );

    for(size_t i = 0; i < items.size(); ++i)
        if( contains( inds, i ) ) // magic O(1) function, never mind
            new_items.push_back( std::move( items[i] ) );

    items.swap(new_items);
}

我的问题是:

1) 在 vector(或通常任何其他标准容器)内的某些元素上使用 std::move 后,是否会出现这些元素的双重破坏等问题?

2) 是否有一种标准方法可以有效地进行此类过滤?

防止搬家可能引起的问题不是集装箱的责任。只要被移动的项目的类型有一个定义明确且正确的移动构造函数/隐式移动构造函数,那么将项目从 items 移动到 new_items 就与任何其他移动操作相同;容器不会改变这一点。

简而言之,这个责任在于 class,而不是它所使用的容器。

您从中移出的对象处于有效但未指定的状态,并且可以在它们上调用没有前提条件的函数。并且析构函数必须是没有前提条件的函数。如果 SomeType 不满足此条件,则它是错误格式的。

所以不会有双重破坏的问题。