【发布时间】:2015-05-10 07:58:52
【问题描述】:
我正在寻找确认,澄清此代码是否定义良好。
通过将迭代器重新分配给容器的erase() 函数的结果,在循环中擦除容器的元素是很常见的。循环通常像这样有点混乱:
struct peer { int i; peer(int i): i(i) {} };
int main()
{
std::list<peer> peers {0, 1, 2, 3, 4, 5, 6};
for(auto p = peers.begin(); p != peers.end();) // remember not to increment
{
if(p->i > 1 && p->i < 4)
p = peers.erase(p);
else
++p; // remember to increment
}
for(auto&& peer: peers)
std::cout << peer.i << ' ';
std::cout << '\n';
}
输出: 0 1 4 5 6
在我看来,假设它没有调用未定义的行为,以下可能会更整洁:
struct peer { int i; peer(int i): i(i) {} };
int main()
{
std::list<peer> peers {0, 1, 2, 3, 4, 5, 6};
for(auto p = peers.begin(); p != peers.end(); ++p)
if(p->i > 1 && p->i < 4)
--(p = peers.erase(p)); // idiomatic decrement ???
for(auto&& peer: peers)
std::cout << peer.i << ' ';
std::cout << '\n';
}
输出: 0 1 4 5 6
我认为这行得通的原因如下:
peers.erase()将始终返回递增的p,因此再次递减它是安全的peers.erase(p)制作了p的副本,因此它不会因reference 排序而对错误值进行操作p = peers.erase(p)返回一个p&,因此减量作用于正确的对象reference。
但我有一些琐碎的疑问。我担心我在使用p 作为参数的同一表达式中使用--(p) 来调用错误的排序规则,尽管它在纸上看起来没问题。
任何人都可以在这里看到我的评估有问题吗?还是这个定义好?
【问题讨论】:
-
我会坚持使用第一个版本 - 一开始它更具可读性
-
在排序方面没有问题,因为这些是重载的运算符 - 即函数调用。
标签: c++ stl containers undefined-behavior erase