What is the official behavior of the range constructor std :: vector when the first itr comes after the last?

Assuming you have a valid starting point:

std::vector<UINT32> host = {1,2,3,4,5}; 

When you try to build another vector using iterators:

 std::vector<UINT32> client(host.begin(),host.end()); // client.size() is 5. Elements begin -> end look just like host. 

But what happens if the iterators are backwards? What if the start is complete?

 std::vector<UINT32> backwardsClient(host.end(), host.begin()); // What happens? 
+6
source share
5 answers

This will be undefined behavior.

A look at the standard:

N3690 23.3.7.2 [vector.cons]

 template <class InputIterator> vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); 

9. Effects: Creates a vector equal to the range [first, last] using the specified allocator.

It says that the range should be [first, last] , but the standard does not mention what happens if it is not. Therefore, this behavior is undefined.

+4
source

The behavior is undefined. The requirements for this constructor are specified in C ++ 11 [sequence.reqmts]Β§3+4 :

3 In tables 100 and 101, X denotes the class of the container of the sequence, a denotes the value of X containing elements of type T , ..., i and j denote iterators satisfying the requirements of the input iterator, and refer to elements implicitly convertible to value_type , [i, j) denotes a valid range, ...

(my emphasis)

Β§4 is a table 100 that determines what X a(i, j) does.

In other words, it is determined only if [i, j) is a valid range, which is not the case in your case. Therefore, the behavior is not defined.

+3
source

First we will visit 24.2.1 / 7 to find out what the valid range is:

Range [i,j) is valid if and only if j is reachable from i. The result of the application of functions in the library to invalid ranges is undefined.

Then simply consider the vector constructor in the requirements of the container container for the 23.2.3 / table 100 sequence, noting that it requires an iterator range, which from the previous section must be valid. This means that in the above example, you have undefined behavior.

+2
source

I would say that this will lead to undefined behavior.

According to http://cppreference.com , vector::vector(first, last) accepts an input iterator, and, with regard to iteration, this category of iterators is only required to provide operator!= And operator++ .

The vector constructor will basically run a loop equivalent to:

 while (first != last) { push_back(*first); ++first; } 

This will cause an infinite loop, but can be protected by the implementation of the standard library with some statement (at least in debug builds).

+1
source

According to http://www.cplusplus.com/reference/vector/vector/vector/ :

(3) range constructor Creates a container with as many elements as the range [first, last], each element constructed from the corresponding element in this range, in the same order.

first, last

Introduce iterators at the start and end positions in the range. The range used is [first, last), which includes all elements between the first and last, including the element indicated by the first, but not the element indicated by the last.

In your case, the range [host.end(), host.begin()) will try to include the element specified by host.end() , and this will cause an error when deleting a link to an iterator of the end of the past.

+1
source

All Articles