为什么插入使 std::set 反向迭代器无效 [英] Why does insert invalidate the std::set reverse iterator

查看:17
本文介绍了为什么插入使 std::set 反向迭代器无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的理解是关联容器的迭代器在插入或擦除期间不会失效(除非迭代器指向的节点被擦除).但是在下面的程序中插入似乎使迭代器无效.是不是我的理解错了?

My understanding is the iterators of associative containers are not invalidated during insert or erase (unless the node pointed by iterator is erased). But in the below program the insert seems to invalidate the iterator. Is my understanding wrong?

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

=====

推荐答案

标准容器迭代器的承诺行为不适用于该容器的反向迭代器.

The promised behavior for iterators of a standard container does not hold for reverse iterators of that container.

反向迭代器实际上将正常(向前移动的)迭代器存储为成员,它在取消引用时位于反向迭代器所引用的元素之后.然后,当您取消引用反向迭代器时,本质上它会递减这个存储的普通迭代器的副本并取消引用它.所以这是一个问题:

A reverse iterator actually stores, as a member, the normal (forward moving) iterator which comes after the element to which the reverse iterator refers when dereferenced. Then when you dereference the reverse iterator, essentially it decrements a copy of this stored normal iterator and dereferences that. So this is a problem:

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

反向迭代器的行为是这样的,因为没有before begin"迭代器.如果他们将迭代器存储到他们实际引用的元素中,rs.rend() 会存储什么?我确信有办法解决这个问题,但我想他们需要标准委员会不愿意做出的妥协.或者他们可能从未考虑过这个问题,或者认为它不够重要.

Reverse iterators behave this way because there is no "before begin" iterator. If they stored the iterator to the element to which they actually refer, what would rs.rend() store? I'm sure there are ways around this, but I guess they required compromises which the standards committee was not willing to make. Or perhaps they never considered this problem, or didn't consider it significant enough.

这篇关于为什么插入使 std::set 反向迭代器无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆