如果我交换两个向量,它们的迭代器是否仍然有效,现在只是指向“其他”容器,或者迭代器是否会失效?
即,给定:
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(vector<T,Allocator>& x);
效果: 交换内容和容量() *与x的那个。
请注意,因为我在VS 2005上,我也对迭代器调试检查等的影响感兴趣(_SECURE_SCL)
答案 0 :(得分:29)
在C ++ 11中,交换的行为已经大大澄清,很大程度上允许标准库算法使用参数相关查找(ADL)来查找用户定义类型的交换函数。 C ++ 11添加了一个可交换的概念(C ++11§17.6.3.2[swappable.requirements]),以使其合法(并且是必需的)。
C ++ 11语言标准中解决您问题的文本是容器需求中的以下文本(§23.2.1[container.requirements.general] / 8),它定义了{{1容器的成员函数:
在交换之前引用一个容器中的元素的每个迭代器都应该在交换后引用另一个容器中的相同元素。
未指定交换前值为
swap
的迭代器在交换后是否具有值a.end()
。
在您的示例中,b.end()
保证在交换后有效,但a
不是因为它是结束迭代器。在第23.2.1 / 10号的说明中解释了最终迭代器无法保证有效的原因:
[注意:
b
迭代器不引用任何元素,因此它可能是 无效。 - 后注]
这与C ++ 03中定义的行为相同,只是基本上澄清了。 C ++ 03的原始语言是C ++03§23.1/ 10:
no
end()
函数使任何引用,指针或迭代器无效,引用要交换的容器的元素。
在原始文本中并不是很明显,但是“对容器的元素”这一短语非常重要,因为swap()
迭代器不指向元素。
答案 1 :(得分:13)
交换两个向量不会使迭代器,指针和对其元素的引用无效(C ++ 03,23.1.11)。
通常,迭代器将包含其容器的知识,并且交换操作会为给定的迭代器维护它。
在VC ++ 10中,使用<xutility>
中的此结构管理向量容器,例如:
struct _Container_proxy
{ // store head of iterator chain and back pointer
_Container_proxy()
: _Mycont(0), _Myfirstiter(0)
{ // construct from pointers
}
const _Container_base12 *_Mycont;
_Iterator_base12 *_Myfirstiter;
};
答案 2 :(得分:3)
答案 3 :(得分:1)
对于Visual Studio 2005,我刚刚测试过它。 我认为它应该始终有效,因为vector :: swap函数甚至包含交换所有内容的明确步骤:
// vector-header
void swap(_Myt& _Right)
{ // exchange contents with _Right
if (this->_Alval == _Right._Alval)
{ // same allocator, swap control information
#if _HAS_ITERATOR_DEBUGGING
this->_Swap_all(_Right);
#endif /* _HAS_ITERATOR_DEBUGGING */
...
迭代器指向现在交换的矢量对象中的原始元素。 (即,对于OP,他们首先指向x
中的元素,在交换之后它们指向y
中的元素。)
请注意,在n3092草案中,要求在§23.2.1/ 9中列出:
每个迭代器都指的是 在之前的一个容器中的元素 交换应指相同的元素 在交换后的另一个容器中。