Reputation: 579
I have a class representing a string of space-delimited words via a vector of those words and an iterator over the vector.
class WordCrawler{
public:
WordCrawler(std::string, bool reversed=false);
WordCrawler& operator--();
std::string operator* () const;
bool atBeginning() const;
private:
std::vector<std::string> words;
std::vector<std::string>::iterator it;
};
I am trying to print out the words in reverse order, using this function:
void print_in_reverse(std::string in) {
WordCrawler wc = WordCrawler(in, true);
while (!wc.atBeginning()) {
--wc;
std::cout << *wc << " ";
}
}
I construct my WordCrawler
object with this constructor:
WordCrawler::WordCrawler(std::string in, bool reversed) {
std::istringstream iss(in);
std::string token;
while (std::getline(iss, token, ' '))
{
words.push_back(token);
}
if (reversed) {
it = words.end();
} else {
it = words.begin();
}
}
The rest of the member functions are pretty simple:
/**
True if pointer is at the beginning of vector
*/
bool WordCrawler::atBeginning() const {
return it == words.begin();
}
/**
Function that returns the string stored at the pointer's address
*/
std::string WordCrawler::operator*() const {
return *it;
}
/**
Function that increments the pointer back by one
*/
WordCrawler& WordCrawler::operator--() {
if (!atBeginning())
--it;
return *this;
}
I'm finding that everything works fine on Xcode and cpp.sh, but on Visual Studio it throws a runtime error saying vector iterators incompatible
at atBeginning()
function. My assumption would be that this is because the code is reliant on some sort of undefined behavior, but as I am relatively new to C++ I'm not sure what it is.
I know that it
is always an iterator of the words
vector, and I know that words
does not change after it
has been initialized, so I'm not sure what the issue is.
Full code at: http://codepad.org/mkN2cGaM
Upvotes: 2
Views: 2158
Reputation: 141586
Your object has a rule of three violation - on copy/move construction the iterator will still point to the vector in the old object.
The line WordCrawler wc = WordCrawler(in, true);
specifies a copy/move operation, triggering this problem. Most compilers perform copy elision here but I heard that older versions of MSVC don't, in debug mode anyway.
To fix this properly, I would recommend using an index instead of an iterator in the class. If you really want to use the iterator you will need to implement your own copy-constructor and move-constructor.
Changing that line to WordCrawler wc(in, true);
would probably fix this particular program but the same problem would be lurking still, and might show up when you make further modifications later.
Upvotes: 4