I have a program I wrote on my linux machine. It uses a std::vector<std::string>
and I loop over it with a for loop like so
std::vector<std::string> words;
words.push_back("A");
words.push_back("B");
words.push_back("C");
// loop
for (auto it = words.end(); it >= words.begin(); it--)
{
std::string word = *it; // invalid deref?
// do things with word
if (word == "B")
{
words.erase(it);
}
std::cout << word << std::endl;
}
int i = 0;
for (std::string word : words)
{
std::cout << i++ << word << std::endl;
}
This runs as expected using g++ as the compiler, printing C, B and A. However when I run it with VisualStudio I get an invalid dereferencing exception.
I run through the vector backwards, because I want to delete items from it, and that messes with the iterator if you loop forwards.
I have a workaround using an integer and getting the items with std::vector<std::string>.at(int)
, but I am curious why this works with my linux machine but not windows?
As you correctly commented, there is an invalid dereferencing.
std::string word = *it;
Will be std::string word = *words.end()
in the first iteration which results in undefined behaviour. So it's perfectly valid that it works on one system and throws an exception on another.
The correct way to reverse-iterate a vector would be
for(auto it = words.rbegin(); it != words.rend(); it++) {...}
However, for deleting elements from a vector, the erase-remove-idiom might be more useful:
words.erase(std::remove(words.begin(), words.end(), "B"), words.end());
Or if you have a more complex condition, use a lambda:
words.erase(std::remove_if(
words.begin(),
words.end(), [](const std::string &name){return name == "B";}
), names.end());