【发布时间】:2015-12-23 23:18:26
【问题描述】:
我试图理解向量中迭代器失效的概念。 从我所做的一些阅读中,我发现如果一个向量包含 7 个元素并且你删除了第 5 个索引上的元素,那么从第 5 个元素开始的迭代器就会失效。这是因为第 5 个索引之后的所有元素都需要向上移动一个插槽。这对我来说很有意义,但是我对以下两种情况有点困惑
std::vector<foo> vec {foo{1},foo{2}}; //foo is a simple class
foo* ptr = &vec[0]; //Case 1
std::vector<foo>::iterator it = vec.begin() + 1; //Case 2
对于 STL 容器,如果迭代器失效,那么指针也会失效,这是否安全?例如,如果it 失效,ptr 也会失效吗?如果不是,您能否给出迭代器无效但指针仍然有效的情况?我目前对向量、地图和双端队列感兴趣。
更新: 所以我写了一点代码并进行了实验
std::vector<foo> vec {foo{1},foo{2},foo{3}};
foo* ptr = &vec[1];
std::vector<foo>::iterator it = vec.begin() + 1;
std::cout << "Before : " << ptr->a << "\n";
vec.erase(vec.begin() + 1); //Remove the second element
std::cout << "Iterator value : " << it->a << "\n";
std::cout << "After : " << ptr->a << "\n";
结果是
Before : 2
Iterator value : 3
After : 3
我很惊讶为什么向量没有提到迭代器无效,因为这是在删除元素之前获得的迭代器。
【问题讨论】:
-
这些向量操作使向量中的所有指针、迭代器和对象引用无效
-
您可以通过考虑容器必须如何管理其缓冲区、缓冲区或对象,并应用该标准旨在允许有效实施的规则来推断出大多数关于失效的规则。
-
Re 指针,标准使用短语“迭代器和引用”,对于任何实际解释都包括指针。这并不意味着所有这些指针都成为无效指针。擦除索引
i处的单个项目,指针&v[i],&v[i+1],直到并包括现在的最后一个项目,简单地引用具有可能更改值的对象(向上移动一个槽,正如你所说的那样)。向量的缓冲区保证是连续的,因此只要其中至少一个指针作为指针保持有效,其他(在新大小内)也必须作为指针有效。 -
@Cheersandhth.-Alf 这是否意味着如果我有一个指向总共有 3 个元素的容器中的第二个元素的指针,并且我还有一个指向第二个元素的迭代器。现在,如果我删除第二个元素,元素 2 和 3rd 的迭代器将变得无效,但是指针将简单地指向新元素(这将是 3rd)?
-
@JamesFranco:在正式的迂腐中你是对的,因为有可能创建一个不正当的
vector实现来跟踪迭代器并对它们做不圣洁的事情(它不能保持跟踪指针)。但在实践中,迭代器和指针是一样的。它们正式失效,这意味着它们不再指向具有与以前相同的值的对象,但它们仍然引用相同的对象。但是请注意,一个项目的erase会导致该项目以前在最后被销毁。此类对象有特殊规则,已死但有存储。