C++ STL: Trouble with string iterators
I'm making a simple command line Hangman game.
void Hangman::printStatus()
{
cout << "Lives remaining: " << livesRemaining << endl;
cout << getFormattedAnswer() << endl;
}
string Hangman::getFormattedAnswer()
{
return getFormattedAnswerFrom(correctAnswer.begin(), correctAnswer.end());
}
string Hangman::getFormattedAnswerFrom(string::const_iterator begin, string::const_iterator end)
{
return begin == end? "" : displayChar(*begin) + getFormattedAnswerFrom(++begin, end);
}
char Hangman::displayChar(const char c)
{
return c;
}
(Eventually, I'll change this so displayChar()
displays a -
or a character if the user has guessed it, but for simplicity now I'm just returning everything.)
When I build and run this from VS 2010, I get a popup box:
Debug Assertion Failed!
xstring Line: 78
Expression: string iterator not dereferenceable
What am I doing 开发者_如何学编程wrong?
The problem is in the evaluation of:
displayChar(*begin) + getFormattedAnswerFrom(++begin, end)
In executing this statement, it is evident that your compiler is first incrementing begin
, returning the "next" begin
for use as the first argument to getFormattedAnswerFrom
, and then dereferencing begin
for the argument to displayChar
.
When begin
is one behind end
, then begin != end
so displayChar(*begin) + getFormattedAnswerFrom(++begin, end)
will run. Your compiler increments begin
, so now begin == end
, and the dereference of begin
is invalid.
See also: Order of evaluation in C++ function parameters
If correctAnswer
is empty, correctAnswer.begin()
will be the same as correctAnswer.end()
and not be dereferenceable.
It seems fine to me. However, remember any heap or stack corruption could produce this error. You need to grab the stack trace and look inside correctAnswer, and ensure that both it and the instance of Hangman in question are valid objects.
Also, I'm just flat out a little concerned about your functions here. They seem very strange. Why not just replace with std::for_each?
Edit@comment:
If you have C++0x, you can just do
std::for_each(correctAnswer.begin(), correctAnswer.end(), [this](const char& ref) {
std::cout << this->displayChar(ref);
});
Else, you will have to do something that looks a little like this:
struct helper {
Hangman* ptr;
void operator()(const char& ref) {
std::cout << ptr->displayChar(ref);
}
};
helper Helper;
Helper.ptr = this;
std::for_each(correctAnswer.begin(), correctAnswer.end(), Helper);
精彩评论