【发布时间】:2019-02-12 14:56:03
【问题描述】:
我知道代码不是好习惯,所以问题不在于那个。我只想了解以下示例的工作原理。请注意,当我调用 remove 时,我不对迭代器做任何事情,所以当循环进入下一次迭代时,它是如何指向下一个元素的?
#include <string>
#include <list>
#include <algorithm>
#include <iostream>
class Obj;
std::list<Obj> objs;
class Obj
{
public:
Obj(const std::string& name, int age)
: name_(name), age_(age)
{}
std::string name()
{
return name_;
}
int age()
{
return age_;
}
private:
std::string name_;
int age_;
};
void remove(const std::string& name)
{
auto it = find_if(objs.begin(), objs.end(),[name] (Obj& o) { return (o.name() == name); });
if (it != objs.end())
{
std::cout << "removing " << it->name() << std::endl;
objs.erase(it);
}
}
int main()
{
objs.emplace_back("bob", 31);
objs.emplace_back("alice", 30);
objs.emplace_back("kevin", 25);
objs.emplace_back("tom", 45);
objs.emplace_back("bart", 37);
objs.emplace_back("koen", 48);
objs.emplace_back("jef", 23);
objs.emplace_back("sara", 22);
auto it = objs.rbegin();
while (it != objs.rend())
{
std::cout << it->name() << std::endl;
if (it->name() == "tom")
{
remove(it->name()); //notice I don't do anything to change the iterator
}
else
{
++it;
}
}
return 0;
}
以下是输出:
sara
jef
koen
bart
tom
removing tom
kevin
alice
bob
【问题讨论】:
-
您的代码具有未定义的行为,因为您更改了使所有迭代器无效的列表。也请不要使用全局变量。
-
@Swordfish "你改变了使所有迭代器无效的列表" - 不,它没有; "References and iterators to the erased elements are invalidated. Other references and iterators are not affected.".
-
@DanielLangr 确实如此并且变得无效。很抱歉我之前评论的措辞有误,并非*所有*迭代器都无效。
-
@Swordfish 是的,只删除了一个,虽然在下一步中会引用它,所以就足够了。
-
@luk32 “这就够了”这应该是什么意思?在
remove(it->name());之后通过it->name()访问它是未定义的行为。严格来说,it != objs.rend()也是。
标签: c++ list c++11 iterator reverse-iterator