我可以根据指针值从std :: list中删除一个项目吗?

时间:2011-09-08 14:55:10

标签: c++ stl

此代码是在飞行中编写的,如果有的话,请忽略语法错误。

std::list<MY_STRUCT> myList;

MY_STRUCT theStruct;

myList.push_back( theStruct );
myList.push_back( theStruct );

// assume I store the pointer of the last item (the 2nd item in this case).
MY_STRUCT * item2 = &myList.back();

// I added another item
myList.push_back( theStruct );

// now I want to delete item2 that I stored bases on its pointer.
// Can myList.remove_if(...) help if so how?

我想通过指针删除列表中的中间项(假设我有指针值)。

我知道我可以遍历列表并查找此指针,但有更好的方法吗? STL是否提供了执行此操作的功能。在这种情况下,我可以使用remove_if()来删除项目吗?

4 个答案:

答案 0 :(得分:4)

为什么不保留迭代器,而不是保留指向要删除的对象的指针?

std::list<MY_STRUCT>::iterator item2 = --mylist.end();

remove_if算法实际上并没有删除任何东西,它只是改变了东西。它不知道迭代器指向的容器。当然,std :: list的成员函数remove_if与注释中指出的完全不同。

答案 1 :(得分:2)

当然,list::remove_if会使用您提供的任何条件。例如

template <typename T>
struct AddressIs {
    T *ptr;
    AddressIs(T *ptr) : ptr(ptr) {}
    bool operator()(const T &object) const {
        return ptr == &object;
    }
};

myList.remove_if(AddressIs<MY_STRUCT>(item2));

Mankarse的观点很好 - 如果你可以使用迭代器而不是指针来识别你感兴趣的项目,那么你就不需要搞砸了。

请注意,我们依赖于list中项目的地址永远保持不变的事实。并非所有集合都是如此,例如vector在调用push_back时可能必须重新定位所有数据。如果是,则item2不再指向您的中间项目。每个集合都记录了哪些操作可以使迭代器和/或元素引用无效。

答案 2 :(得分:2)

不是获取back项,而是获取end迭代器,确保它不是begin,减1指向最后一项,然后{{1只要你想要就直接迭代。

答案 3 :(得分:0)

我认为对于zadane试图做的事情,remove_if有点过分。所有需要完成的工作是保存项目的位置或值,以便稍后删除该特定项目。

正如Mark建议您可以将迭代器存储到对象中并使用它来删除带有擦除调用的项目,如下所示:

MY_STRUCT struct;
myList.push_back(struct);
myList.push_back(struct);
std::list<MY_STRUCT>::iterator del_it = myList.end() - 1;
myList.erase(del_it);

或者,如果您的结构具有为MY_STRUCT定义的==运算符,则可以存储对象本身的值并使用remove方法

MY_STRUCT struct1;
MY_STRUCT struct2;
myList.push_back(struct1);
myList.push_back(struct2);
myList.remove(struct2);

当然,如果您将列表作为指针列表,那么您不必担心==运算符,因为它已经为指针类型定义。只需确保如果您在列表中进行迭代并调用erase,则需要使用返回值更新迭代器。

此外,remove方法删除传递值的所有元素,因此如果您只想一次删除1个项目,请保存迭代器而不是值。

此代码未经测试,因此我欢迎任何更正。