Does std :: vector :: swap use nullify iterators?

If I swap two vectors, will their iterators remain valid now simply pointing to the “other” container, or will the iterator be invalid?

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? 

Std doesn't seem to say anything 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 am also interested in the effects of checking iterator debugging, etc. (_SECURE_SCL)

+39
c ++ iterator visual-c ++ stl
Nov 08 2018-10-11
source share
4 answers

The behavior of swap is much clarified in C ++ 11, largely to allow the standard library algorithms to use dependency-dependent search (ADL) to search for swap functions for user types. C ++ 11 adds the concept of swappable (C ++ 11 §17.6.3.2 [swappable.requirements]) to make this legal (and mandatory).

The text in the standard C ++ 11 language that answers your question is the following text from the requirements of the container (§23.2.1 [container.requirements.general] / 8) that defines the behavior of the swap container member function:

Each iterator that refers to an element in one container before the swap must refer to the same element in another container after the exchange.

It is not indicated whether there will be an iterator with a.end() value before swap has b.end() value after the swap.

Your example guarantees that a will be valid after the exchange, but b not because it is an end iterator. The reason that iterators end is not guaranteed to be valid, is explained in the note in §23.2.1 / 10:

[Note: the end() iterator does not refer to any element, therefore it can be nullified. - note]

This is the same behavior that is defined in C ++ 03, just clarified. The source language from C ++ 03 is in C ++ 03 §23.1 / 10:

Function

no swap() invalidates any references, pointers, or iterators that reference elements of exchanged containers.

This is not immediately visible in the source text, but the phrase "container elements" is extremely important because end() iterators do not point to elements.

+28
Nov 08 '10 at 3:23 a.m.
source share

The exchange of two vectors does not negate iterators, pointers, and references to its elements (C ++ 03, 23.1.11).

Typically, an iterator will contain information about its container, and the swap operation supports this for a given iterator.

In VC ++ 10, a vector container is managed using this structure in <xutility> , for example:

 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; }; 
+13
Nov 08 2018-10-10T00:
source share
+3
Nov 08 2018-10-10T00:
source share

As for Visual Studio 2005, I just tested it. I think it should always work, as the vector :: swap function even contains an explicit step to replace everything:

  // 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 */ ... 

Iterators point to their source elements in a vector object with a replacement now. (Iew / rg to OP, they first pointed to elements in x , after swapping they point to elements in y .)

Please note that in project n3092 the requirement is set out in paragraph 23.2.1 / 9:

Each iterator that refers to an element in one container before swapping refers to the same element in another container after the exchange.

+1
Nov 08 2018-10-10
source share



All Articles