std::vector::swap 是否使迭代器无效?
如果我交换两个向量,它们的迭代器会保持有效,现在只是指向其他"容器,还是迭代器会失效?
If I swap two vectors, will their iterators remain valid, now just pointing to the "other" container, or will the iterator be invalidated?
也就是说,给定:
using namespace std;
vector<int> x(42, 42);
vector<int> y;
vector<int>::iterator a = x.begin();
vector<int>::iterator b = x.end();
x.swap(y);
// a and b still valid? Pointing to x or y?
std 似乎对此只字未提:
It seems the std mentions nothing about this:
[n3092 - 23.3.6.2]
[n3092 - 23.3.6.2]
void swap(vector
效果:交换内容和容量()*this 与 x 的.
Effects: Exchanges the contents and capacity() of *this with that of x.
请注意,由于我使用的是 VS 2005,因此我还对迭代器调试检查等的效果感兴趣.(_SECURE_SCL)
Note that since I'm on VS 2005 I'm also interested in the effects of iterator debug checks etc. (_SECURE_SCL)
推荐答案
在 C++11 中,swap 的行为已经得到了相当大的澄清,很大程度上是为了允许标准库算法使用参数依赖查找 (ADL) 来查找用户定义类型的交换函数.C++11 添加了一个swappable 概念(C++11 §17.6.3.2[swappable.requirements])以使其合法(并且是必需的).
The behavior of swap has been clarified considerably in C++11, in large part to permit the Standard Library algorithms to use argument dependent lookup (ADL) to find swap functions for user-defined types. C++11 adds a swappable concept (C++11 §17.6.3.2[swappable.requirements]) to make this legal (and required).
解决您的问题的 C++11 语言标准中的文本是容器要求 (§23.2.1[container.requirements.general]/8) 中的以下文本,它定义了 的行为swap
容器的成员函数:
The text in the C++11 language standard that addresses your question is the following text from the container requirements (§23.2.1[container.requirements.general]/8), which defines the behavior of the swap
member function of a container:
在交换之前引用一个容器中的元素的每个迭代器在交换之后都应该引用另一个容器中的相同元素.
Every iterator referring to an element in one container before the swap shall refer to the same element in the other container after the swap.
未指定交换前值为 a.end()
的迭代器在交换后是否有值为 b.end()
.
It is unspecified whether an iterator with value a.end()
before the swap will have value b.end()
after the swap.
在您的示例中, a
保证在交换后有效,但 b
不是因为它是结束迭代器.无法保证结束迭代器有效的原因在 §23.2.1/10 的注释中进行了解释:
In your example, a
is guaranteed to be valid after the swap, but b
is not because it is an end iterator. The reason end iterators are not guaranteed to be valid is explained in a note at §23.2.1/10:
[注意:end()
迭代器不引用任何元素,因此它可能是无效.--尾注]
[Note: the
end()
iterator does not refer to any element, so it may be invalidated. --end note]
这与 C++03 中定义的行为相同,只是在很大程度上得到了澄清.C++03 的原始语言位于 C++03 §23.1/10:
This is the same behavior that is defined in C++03, just substantially clarified. The original language from C++03 is at C++03 §23.1/10:
没有 swap()
函数使任何引用被交换容器的元素的引用、指针或迭代器无效.
no
swap()
function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped.
在原文中不是很明显,但是到容器的元素"这句话非常重要,因为 end()
迭代器不指向元素.
It's not immediately obvious in the original text, but the phrase "to the elements of the containers" is extremely important, because end()
iterators do not point to elements.
相关文章