3

我今天在 C++ 容器的上下文中了解了这个术语invalidation。谁能解释一下这是什么意思?

在循环容器时,似乎不允许您以某种方式修改容器的元素。但究竟是什么方式?

请帮助我理解这个话题。

谢谢,博达赛多。

4

4 回答 4

5

容器不会失效——引用容器中元素的迭代器会失效。

迭代器是容器中特定项的句柄。只要该项目保留在容器内,并且容器不会在内部重新排列自身,迭代器就有效。当这两种情况之一发生时,迭代器将失效,因为之后迭代器作​​为容器的句柄不再有效。

使迭代器无效的最明显方法是从集合中删除其引用项,例如:

std::set<int> s;

s.insert(4);
s.insert(2);

std::set<int>::iterator itr = s.find(4); // itr is a handle to 4

std::cout << *itr << std::endl; // prints 4

s.erase(4); // removes 4 from collection, invalidates itr

std::cout << *itr << std::endl; // undefined behavior

使迭代器无效的更微妙的方法是使容器在内部重新排列自身(例如重新分配其内部存储)。例如,这可以通过扩展某些类型的容器来完成:

std::vector<int> v;

v.push_back(4);
v.push_back(2);

std::vector<int>::iterator itr = v.begin(); // itr is a handle to 4

std::cout << *itr << std::endl; // prints 4

v.push_back(12); // MIGHT invalidate itr, if v expands its internal allocation

您可以通过预先保留空间来防止某些容器中的这种情况:

std::vector<int> v;

v.reserve(3); // Pre-allocate 3 elements

v.push_back(4);
v.push_back(2);

std::vector<int>::iterator itr = v.begin(); // itr is a handle to 4

std::cout << *itr << std::endl; // prints 4

v.push_back(12); // WILL NOT invalidate itr, since it will never cause v to expand

每个 STL 容器的文档应该描述在什么情况下迭代器失效将会或可能发生。

于 2010-07-27T15:16:11.390 回答
1

当底层容器以某种方式发生变化时,某些迭代器失效。

例如:vector当容器大小改变时迭代器失效。list删除基础数据时,迭代器将失效。

这意味着迭代器不再有效。尝试取消引用它可能会导致异常或未定义的行为。尝试操纵它不能保证有效。

于 2010-07-27T15:11:56.400 回答
0

如果您有一个对象数组(或列表)并在它们上循环,则您删除了一些项目 - 那么数组中的简单索引可能无效,但迭代器仍然有效。

于 2010-07-27T15:10:53.033 回答
0

我认为这都是关于迭代器无效的。有几个例子:

std::vector<int> v1(10);
std::vector<int> v2(11);
//1
for (std::vector<int>::iterator it = v1.begin(); it != v2.end(); ++it);
//2
for (std::vector<int>::iterator it = v1.begin(); it != v1.end(); ++it)
{
    v1.erase(it);
}
于 2010-07-27T15:15:22.697 回答