Re: Iterate beyond the end of container without dereferencing it...
"Frank Yeh" <frank.yeh@gmail.com> writes:
Is "iterate beyond the end of container *without* dereferencing it" an
undefined behaviour?
Yes.
I meet this question when I implement matrix operation code using
Visual Studio 2005 as follows.
void row_operations(void)
{
//simulate a 3x3 matrix using one dimensional array
const size_t row_count = 3;
const size_t col_count = 3;
std::vector<double> matrix(row_count*col_count);
// the following code performs row iterations
std::vector<double>::iterator row_iterator = matrix.begin();
for(size_t row = 0;row < row_count;++row,row_iterator += col_count)
{
// performing operation for each row...
}
}
Visual Studio generates an invalid iterator error in debug mode
right before the end of the loop. Before the end of the loop, row index
is 3 and row_iterator is beyond matrix.end(), but the loop is soon
terminated for row index not less than the row count. In other words,
row_iterator will not be dereferenced when it iterates beyond the end
of the container.
This is the well-known "strided iterator problem." Strided iterator
adaptors always need an end iterator to check against, to avoid going
past it.
Its brings trouble to me that the code was forced to quit because
row_iterator > matrix.end() even if dereferencing is not performed.
I have reported this problem to "Microsoft Connect". A development
lead in Visual C++ Libraries send me a mail with the following
explanation:
"The standard considers moving outside of the container range
undefined (and therefore not required to be supported at all) - so the
code you have is non-portable."
So the standard documented that it is a undefined behaviour to
iterate beyond the end of container even if I don't dereferencing it?
How can I solve the problem except for using naked pointers?
Your choice:
A. By using an extra check to avoid going past the end. Yes, that
will slow your code down
B. By unrolling the last iteration of the loop:
// the following code performs row iterations
std::vector<double>::iterator row_iterator = matrix.begin();
for(size_t row = 0;row < row_count-1;++row,row_iterator += col_count)
{
// performing operation for each row...
}
// perform operation for the last row.
HTH,
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]