【问题标题】:What does container invalidation in C++ mean?C++ 中的容器失效是什么意思?
【发布时间】:2011-03-21 16:12:03
【问题描述】:

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

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

请帮助我理解这个话题。

谢谢,博达·赛多。

【问题讨论】:

标签: c++ containers invalidation


【解决方案1】:

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

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

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

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,还需要注意的是,除了迭代器失效之外,容器中元素的引用和指针也可能在不同时间失效。对于向量,当容器增长时,容器中的所有迭代器、指针和引用都将失效,但对于std::deque,在前面插入可以使迭代器失效,同时使指向所包含元素的引用和指针保持有效。阅读每个容器/操作的文档。
【解决方案2】:

我认为这完全与迭代器无效有关。有几个例子:

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);
}

【讨论】:

    【解决方案3】:

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

    例如:vector 迭代器在容器大小发生变化时失效。 list 迭代器在底层数据被删除时失效。

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 如果迭代器指向的元素被删除会怎样?
      猜你喜欢
      • 2012-09-27
      • 2013-03-09
      • 1970-01-01
      • 2019-09-12
      • 2010-10-12
      • 2016-12-08
      • 2011-07-07
      • 2023-03-27
      相关资源
      最近更新 更多