C++中对一个对象向量使用remove_if函数

47

我有一个对象向量(顺序很重要),其中包含多个对象(我们称之为myobj类),我想一次性删除多个对象。

class vectorList
{

    vector<*myobj> myList; 
};

class myobj
{

    char* myName;
    int index;
    bool m_bMarkedDelete;
}
我想最好的方法是标记要删除的特定myobj对象,然后在vector上调用myList.remove_if()。但是,我不确定如何使用谓词等内容。我应该在对象中创建一个成员变量,允许我声明我想要删除myobj,并创建一个检查成员变量是否设置的谓词吗?
如何将谓词作为vectorList类的一部分实现?

1
可能与此无关,但 std::list 保留顺序并具有自己的 remove_if 函数,速度更快,不需要单独使用 erase。 - Ant
1
@Ant:list::remove_if在向量上比removeerase更快吗?在什么情况下?在我所做的许多合理测试中,这肯定不是这种情况。不要假设仅因为对于列表而言删除是一个常数时间操作,它就会更快。std::vector的连续性和随机访问保证了它有很高的性能。 - Benjamin Lindley
2个回答

66
我应该在对象中创建一个成员变量,以允许我指定要删除myobj,然后创建一个谓词来检查是否设置了该成员变量吗?
你已经这样做了吗?m_bMarkedDelete 不就是为此而存在的吗?你可以像这样编写谓词:
bool IsMarkedToDelete(const myobj & o)
{
    return o.m_bMarkedDelete;
}

那么:

myList.erase(
    std::remove_if(myList.begin(), myList.end(), IsMarkedToDelete),
    myList.end());

或者,使用lambda表达式:

myList.erase(
    std::remove_if(myList.begin(), myList.end(),
        [](const myobj & o) { return o.m_bMarkedDelete; }),
    myList.end());

如果你的类实际上没有那个成员,而你问我们是否应该有这个成员,那么我会说不需要。你是根据什么标准将其标记为删除的?在谓词中使用相同的标准,例如:

bool IndexGreaterThanTen(const myobj & o)
{
    return o.index > 10;
}

注意 -- 我编写的函数当然是无效的,因为你的所有成员都是私有的。因此您需要找到一种访问它们的方法。


@Jordan:它在谈论this指针。这个函数不应该是成员,因此不应该有this指针。 - Benjamin Lindley
是的,我仍然遇到相同的错误。无法将“this”指针从“const myobj”转换为“myobj&” 转换会丢失限定符。这对指针向量也适用吗? - Jordan
@Jordan:你为 m_bMarkedDelete 创建了一个公共访问器,但没有将其设置为 const 吗? - Benjamin Lindley
我现在实际上使用的是整数成员/访问器,而不是布尔值,但我已尝试将其制作为const和非const。访问器是公共的。bool IsMarkedToDelete(const myobj&value) { return (value.GetPredicate() == 1); } - Jordan
2
IsMarkedToDelete 应该是静态函数。 - Erdemus
显示剩余4条评论

16

谓词基本上是一个条件比较。它可以是一个函数或对象。这里是使用新的C++ lambda的示例。这段代码将遍历向量并删除等于3的值。

int arg[6] = {1, 2, 3, 3, 3, 5};
std::vector<int> vec(arg, arg+6);
vec.erase(
   std::remove_if(
      vec.begin(), vec.end(),
      [](int i){ return i == 3;}),
   vec.end());

编辑: 对于指针,假设你有一个接口的向量,你可以将它们设置为nullptr,然后使用几乎相同的代码批量删除它们。在VS2008中,您将没有lambda表达式,因此请改用比较谓词函数或结构体。

bool ShouldDelete(IAbstractBase* i)
{
    return i == nullptr;
    // you can put whatever you want here like:
    // return i->m_bMarkedDelete;
}

std::vector<IAbstractBase*> vec;
vec.erase(
   std::remove_if(
      vec.begin(), vec.end(),
      ShouldDelete),
   vec.end());

如果向量是我的obj*指针列表,我该怎么做呢?这是我困惑的事情之一。这在VS 2008中可以工作吗?谢谢! - Jordan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接