std::vector::swap 是否会使迭代器无效?
如果我交换两个向量,它们的迭代器是否仍然有效,现在只是指向“其他”容器,或者迭代器是否会失效?
也就是说,给定:
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 似乎没有提到这一点:
[n3092 - 23.3.6.2]
void swap(向量
& x); 效果: 交换内容和容量() *this 与 x 的那个。
请注意,由于我使用的是 VS 2005,所以我也对迭代器调试检查等的效果感兴趣。(_SECURE_SCL)
If I swap two vectors, will their iterators remain valid, now just pointing to the "other" container, or will the iterator be invalidated?
That is, given:
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?
It seems the std mentions nothing about this:
[n3092 - 23.3.6.2]
void swap(vector<T,Allocator>& x);
Effects:
Exchanges the contents and capacity()
of *this with that of x.
Note that since I'm on VS 2005 I'm also interested in the effects of iterator debug checks etc. (_SECURE_SCL)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
交换的行为在 C++11 中已得到相当程度的澄清,很大程度上是为了允许标准库算法使用参数相关查找 (ADL) 来查找用户定义类型的交换函数。 C++11 添加了一个可交换概念(C++11 §17.6.3.2[swappable.requirements])以使此合法(且必需)。
C++11 语言标准中解决您问题的文本是容器要求 (§23.2.1[container.requirements.general]/8) 中的以下文本,它定义了
交换的行为 容器的成员函数:
在您的示例中,
a
在交换后保证有效,但b
则不然,因为它是一个结束迭代器。 §23.2.1/10 的注释中解释了末端迭代器不保证有效的原因:这与 C++03 中定义的行为相同,只是进行了实质性澄清。 C++03 的原始语言位于 C++03 §23.1/10:
在原文中并不是很明显,但是短语“指向容器的元素”非常重要,因为
end()
迭代器不指向元素。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).
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:In your example,
a
is guaranteed to be valid after the swap, butb
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: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:
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.交换两个向量不会使迭代器、指针和对其元素的引用无效(C++03、23.1.11)。
通常,迭代器将包含其容器的知识,并且交换操作为给定的迭代器维护这一点。
在 VC++ 10 中,向量容器是使用
中的结构进行管理的,例如:Swapping two vectors does not invalidate the iterators, pointers, and references to its elements (C++03, 23.1.11).
Typically the iterator would contain knowledge of its container, and the swap operation maintains this for a given iterator.
In VC++ 10 the vector container is managed using this structure in
<xutility>
, for example:所有引用容器元素的迭代器仍然有效
All iterators that refer to the elements of the containers remain valid
至于Visual Studio 2005,我刚刚测试过。
我认为它应该始终有效,因为 vector::swap 函数甚至包含交换所有内容的显式步骤:
迭代器指向现在交换的向量对象中的原始元素。 (即 w/rg 到 OP,它们首先指向
x
中的元素,交换后它们指向y
中的元素。)请注意,在 n3092 草案中要求§23.2.1/9 中列出:
As for Visual Studio 2005, I have just tested it.
I think it should always work, as the vector::swap function even contains an explicit step to swap everything:
The iterators point to their original elements in the now-swapped vector object. (I.e. w/rg to the OP, they first pointed to elements in
x
, after the swap they point to elements iny
.)Note that in the n3092 draft the requirement is laid out in §23.2.1/9 :