我的理解是关联容器的迭代器在插入或擦除期间不会失效(除非迭代器指向的节点被擦除).但在下面的程序中,插入似乎使迭代器无效.我的理解错了吗?
typedef std::set<unsigned int> myset_t;
int main(int argc, char **argv)
{
myset_t rs;
myset_t::reverse_iterator rit;
myset_t::reverse_iterator srit;
int ii = 500;
rs.insert(10);
rs.insert(11);
rs.insert(12);
rs.insert(13);
rs.insert(14);
rs.insert(100000);
rs.insert(102000);
rs.insert(103000);
rit = rs.rbegin();
while(rit != rs.rend()) {
srit = rit;
if (*rit < 100000) {
cout << "bailing here " << *rit << endl;
return 0;
}
rit++;
cout << "Before erase " << *rit << endl;
rs.erase(*srit);
cout << "Before insert " << *rit << endl;
rs.insert(ii);
cout << "After insert " << *rit << endl;
ii++;
}
cout << "Out of loop" << endl;
}
===
The output is
Before erase 102000
Before insert 102000
After insert 14
bailing here 14
=====
Run Code Online (Sandbox Code Playgroud)
标准容器的迭代器的承诺行为不适用于该容器的反向迭代器.
反向迭代器实际上存储了正常(向前移动)迭代器,该迭代器位于反向迭代器在解除引用时引用的元素之后.然后当你取消引用反向迭代器时,基本上它会减少这个存储的正常迭代器的副本并解除引用.所以这是一个问题:
rit = rs.rbegin(); // rit stores rs.end()
srit = rit; // srit also stores rs.end()
rit++; // rit stores a normal iterator pointing to the last element
rs.erase(*srit); // this deletes the last element, invalidating the normal
// iterator which is stored in rit. Funnily enough, the
// one stored in srit remains valid, but now *srit is a
// different value
Run Code Online (Sandbox Code Playgroud)
反向迭代器的行为方式是这样的,因为没有"before begin"迭代器.如果他们将迭代器存储到它们实际引用的元素,那么会rs.rend()存储什么?我确信有办法解决这个问题,但我想他们需要妥协,标准委员会不愿意这样做.或许他们从未考虑过这个问题,或者认为它不够重要.