我今天在C ++容器的上下文中了解到术语invalidation
。任何人都可以解释它的含义吗?
在循环容器时,似乎不允许以某种方式修改容器的元素。但究竟是什么方式呢?
请帮助我理解这个主题。
谢谢,Boda Cydo。
答案 0 :(得分: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容器的文档应描述在什么情况下迭代器将失效或可能发生失效。
答案 1 :(得分:1)
某些迭代器会变为无效。
例如:当容器的大小发生变化时,vector
迭代器无效。删除基础数据时,list
迭代器无效。
这意味着迭代器不再有效。尝试取消引用它可能会导致异常或未定义的行为。尝试操纵它并不能保证有效。
答案 2 :(得分:0)
如果你有一个对象的数组(或列表)并循环它们你删除了一些项 - 那么一个简单的数组索引可能无效,但迭代器仍然是。
答案 3 :(得分: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);
}