The following code works as expected (the test passes) but I wonder if working with iterators in this way is considered a bad practice in c++ or if it is okay.
Maybe this is specific for std::vector
and other collections behave differently and best practices vary between collections (or even their implementations)?
It certainly is not okay in other languages and most of the time changing a collection will invalidate iterators and throw exceptions.
BOOST_AUTO_TEST_CASE (ReverseIteratorExample) {
std::vector<int> myvector;
for(int i = 0; i < 5; i++)
{
myvector.push_back(i);
}
// is this generally a bad idea to change the vector while iterating?
// is it okay in this specific case?
myvector.reserve(myvector.size() + myvector.size() - 2 );
myvector.insert(myvector.end(), myvector.rbegin() + 1, myvector.rend() -1);
int resultset [8] = { 0,1,2,3,4,3,2,1 };
std::vector<int> resultVector( resultset, resultset + sizeof(resultset)/sizeof(resultset[0]) );
BOOST_CHECK_EQUAL_COLLECTIONS(myvector.begin(), myvector.end(), resultVector.begin(), resultVector.end());
}
Summarized Questions:
std::vector
and other collections behave differently? An iterator can be generated to traverse through a vector. vector<int>::iterator iter; An iterator is used as a pointer to iterate through a sequence such as a string or vector . The pointer can then be incremented to access the next element in the sequence.
Appending to a vector means adding one or more elements at the back of the vector. The C++ vector has member functions. The member functions that can be used for appending are: push_back(), insert() and emplace(). The official function to be used to append is push_back().
You need to make use of the begin and end method of the vector class, which return the iterator referring to the first and the last element respectively. using namespace std; vector<string> myvector; // a vector of stings. // push some strings in the vector. myvector. push_back("a"); myvector.
This is not valid code. The standard's definition of operations on sequence containers states (23.2.3@4):
a.insert(p,i,j) - [...] pre: i and j are not iterators into a.
So your code invokes undefined behavior because it violates the precondition for the insert
operation.
If instead of using insert
, you wrote a loop iterating from myvector.rbegin() + 1
to myvector.rend() -1
and called push_back
on all values, your code would be valid: This is because push_back
only invalidates vector iterators if a reallocation is needed, and your call to reserve
ensures that this is not the case.
In general, while there are some cases where modifying a container while iterating over it is fine (such as the loop described above), you have to make sure that your iterators aren't invalidated while doing so. When this happens is specific to each container.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With