3

我正在编写一个需要高效功能来过滤成员容器的类(比如说std::vector)。这个函数应该有类似下面的接口:

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

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

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

我的想法是创建第二个容器,保留所需空间,然后将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)在(或通常任何其他标准容器)std::move内的某些元素上使用后,vector是否会出现诸如双重破坏这些元素之类的问题?

2)有没有一种标准方法可以有效地进行这种过滤?

4

2 回答 2

8

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

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

于 2019-08-27T11:59:49.970 回答
-1

您从中移动的对象处于有效但未指定的状态,并且可以在它们上调用没有前置条件的函数。析构函数必须是没有前提条件的函数。如果SomeType不满足这个条件,那么它就是病态的。

所以不存在双重破坏的问题。

于 2019-08-27T11:59:51.277 回答