赋值(operator =)使容器的迭代器无效 [英] Assignment (operator =) invalidates iterators for containers

查看:411
本文介绍了赋值(operator =)使容器的迭代器无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的代码:

I have a code just like this:

std::vector<int> v1 = { 1, 2, 3, 4 };  
std::vector<int> v2 = { 7, 8, 9, 10 };  
std::vector<int>::iterator it = std::next(v1.begin());  
v1 = v2;  
int test = *it;  
std::cout << test;   

上面的代码会抛出一个错误:迭代器不能解除引用。

The above code will throw an error: iterator not dereferencable.

但是,如果我用以下列表替换vector:

However, if I replace vector with list as follows:

std::list<int> v1 = { 1, 2, 3, 4 };  
std::list<int> v2 = { 7, 8, 9, 10 };  
std::list<int>::iterator it = std::next(v1.begin());  
v1 = v2;  
int test = *it;  
std::cout << test;   

代码按预期运行且没有错误。

来自迭代器失效规则 std :: list :: operator = ,在调用operator =后,我被告知,所有与此容器相关的迭代器,引用和指针都是无效,除了结束迭代器。但为什么上面的代码与std :: list有效?我是否误解了必要的内容?

The code just ran as expected without error.
From Iterator invalidation rules, and the std::list::operator=, I was told that after the call to operator =, all iterators, references and pointers related to this container are invalidated, except the end iterators. But why the above code with std::list works? Did I misunderstand something essential?

推荐答案

当迭代器失效时,取消引用它是未定义的行为。因此,就规范而言,无论你采取何种行为都是无关紧要的。根据你的期望,工作是允许的行为之一。

When an iterator is invalidated, dereferencing it is undefined behavior. Therefore, whatever behavior you observed in doing so is irrelevant, as far as the spec is concerned. "Working", according to your expectations, is among the allowable behaviors.

FWIW(不多,tbh),我希望 std: :list 要实现的赋值运算符等效于:

FWIW (not much, tbh), I would expect the std::list assignment operator to be implemented equivalent to something like this:

list& operator=(list const& rhs) {
    if (this == &rhs)
        return *this;

    auto lhs_i = begin();
    auto rhs_i = rhs.begin();

    // write over the elements in any currently existing nodes, this
    // avoids any unnecessary allocations
    while (lhs_i != end() && rhs_i != rhs.end()) {
        *lhs_i++ = *rhs_i++;
    }

    // erase any extra elements if size() > rhs.size()
    erase(lhs_i, end());

    // push back additional elements if size() < rhs.size()
    while (rhs_i != rhs.end()) {
        push_back(*rhs_i++);
    }

    return *this;
}

如果是,你可以看到,对于像你这样的案例,其中列表具有相同数量的元素,没有创建或销毁任何元素,因此您非常希望迭代器继续正常工作。当然,这完全是猜测,绝对不是你应该依赖的行为,因为即使是你的实现情况,他们也可以在下一个版本中更改它而不另行通知。

And if it is, you can see that, for a case such as yours, where the lists both have the same number of elements, no elements are created or destroyed, and so you would very much expect iterators to go on working exactly as normal. This is, of course, entirely speculation, and definitely not behavior which you should rely on because even if it is the case for your implementation, they can change it on the next release without notice.

这篇关于赋值(operator =)使容器的迭代器无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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