JackCarmichael
JackCarmichael

Reputation: 49

Switching Vectors Supplied Iterators

I am designing my own generic tree container and am using the STL as a reference. However, when implementing my iterator class I noticed something about the STL's use of iterators.

As an example, the std::vector class relies on iterators as arguments for many of its methods. (ie. erase(const_iterator position))

This got me wondering: what happens if, given two vectors of the same template type, and the first vectors iterator is supplied to the second vector in a method call, what happens? To help answer this question I have put together a simple program to illustrate my thoughts.

// Example program
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>

void printVec(const std::string &label, const std::vector<int> &vec){
    for (unsigned int i=0; i<vec.size(); i++){
        std::cout << ::std::setw(3) << vec[i] << ", ";
    }
    std::cout << std::endl;
}

int main()
{
  std::vector<int> test={0,1,2,3,4,5,6,7,8,9};
  std::vector<int> test2{10,11,12,13,14,15,16,17,18,19};
  std::vector<int>::iterator iter=test.begin();
  std::vector<int>::iterator iter2=test2.begin();

  printVec("One",test);
  printVec("Two",test2);

  for (int i=0; i<5; i++, iter++, iter2++);
  std::cout << "One Pos: " << *iter << std::endl;
  std::cout << "Two Pos: " << *iter2 << std::endl;
  test.erase(iter2);    //Switching the iterators and there respective vectors
  test2.erase(iter);    //Switching the iterators and there respective vectors

  printVec("One",test);
  printVec("Two",test2);
}

Running this program results in a seg. fault, which seems to indicate that this is undefined behavior. I hesitate to call this a flaw in the STL vector interface, but it sure seems that way.

So my question is this: is there any way to avoid this when designing my own container?

Upvotes: 0

Views: 23

Answers (1)

1201ProgramAlarm
1201ProgramAlarm

Reputation: 32717

The iterator passed to a member function of a container must refer to an element within that container (or, in some cases, the past-the-end element returned by end()). If the iterator does not refer to the container you have Undefined Behavior.

There is no simple way to avoid that. About the closest you can come is to validate the iterators, which means you'd have to keep track of the container each iterator belongs to. This gets a bit complicated with some operations like swap or insert that don't invalidate existing iterators but leave them referring to the new container.

Some compilers, like Visual C++ when compiling in debug mode, can detect these sorts of problems at runtime and issue an appropriate notification.

Upvotes: 1

Related Questions