gpt4 book ai didi

c++ - 为什么 vector::pop_back 会使迭代器 (end() - 1) 无效?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:43:46 27 4
gpt4 key购买 nike

注意:该问题也适用于erase。见底部。


end() - 1 迭代器在 vector 上调用 pop_back 后无效的原因是什么?

为了澄清,我指的是这种情况:

std::vector<int> v;
v.push_back(1);
v.push_back(2);

std::vector<int>::iterator i1 = v.begin(), i2 = v.end() - 1, i3 = v.begin() + 1;

v.pop_back();

// i1 is still valid
// i2 is now invalid
// i3 is now invalid too

std::vector<int>::iterator i4 = v.end();

assert(i2 == i4); // undefined behavior (but why should it be?!)
assert(i3 == i4); // undefined behavior (but why should it be?!)

为什么会这样? (即这种无效何时会证明对实现有益?)

(请注意,这不仅仅是一个理论问题。Visual C++ 2013 - 可能还有 2012 - 如果您尝试在 Debug模式下执行此操作,如果您有 _ITERATOR_DEBUG_LEVEL 设置为 2。)


关于删除:

请注意,同样的问题适用于erase:
为什么 erase(end() - 1, end()) 会使 end() - 1 无效?

(所以请不要说,pop_back 使 end() - 1 无效,因为它等同于调用 erase(end() - 1, end())";这只是在回避问题。)

最佳答案

有趣的问题是迭代器失效究竟意味着什么。我真的没有从标准中得到一个好的答案。我所知道的是,在某种程度上,标准认为迭代器不是指向容器内某个位置的指针,而是容器内特定元素的代理。

考虑到这一点,在删除 vector 中间的单个元素后,删除点之后的所有迭代器都变得无效,因为它们不再引用它们引用的同一个元素之前。

对这一推理的支持来自容器中其他操作的迭代器失效子句。例如,在 insert 上,标准保证如果没有重新分配,插入点之前的迭代器保持有效。 Exceptio probat regulam in casibus non exceptis,它使插入点之后的所有迭代器无效。

如果迭代器的有效性仅与迭代器指向的容器中有一个元素这一事实有关,那么没有的迭代器将因该操作而失效(同样,在没有重新分配)。

在这一推理中更进一步,如果您将迭代器有效性视为指针有效性,那么在erase 操作期间, vector 中的所有迭代器都不会失效. end()-1 迭代器将变为不可取消引用,但它可能仍然有效,但事实并非如此。

关于c++ - 为什么 vector::pop_back 会使迭代器 (end() - 1) 无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17778816/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com