[C++] Iterator: Assert Failed. Why Assert Fails Here?

Started by
12 comments, last by Concentrate 13 years, 3 months ago
I have a polynomial class, which stores the coefficients of a polynomial inside an std::vector container. "i"th element of the vector is the coefficient of the x-term whose power is "i". After several arithmetic operations, some highest degree terms may be zero. Therefore, I want to clean these ending zero terms.

For instance, assume that, after an addition operation, the actual result is:
P(x) = 1.2 + 3.4x - 6.0x^2 + 5.9x^4
But it is stored as:
[1.2; 3.4; -6.2; 0.0; 5.9; 0.0; 0.0]
I want to remove the last two zero terms.

My code is this:


template<class T> // "T" is "long double" for this instance
void Polynomial<T>::CleanZeroCoefficients()
{
for (std::vector<T>::const_iterator it=m_Coefficients.end(); it!=m_Coefficients.begin(); it--)
{
if (*it == static_cast<T>(0)) // Exception given at this line
{
// Definition: "std::vector<T> m_Coefficients;"
m_Coefficients.erase(it);
}
else
{
break;
}
}
}


This code gives this exception:
exception.png

What is wrong with this code, and how do I fix it?

Thanks.

(IDE: Visual Studio 2010)
Advertisement
If you want to iterate over the vector in reverse order, you need to use rbegin() and rend(). end() is never a dereferencable iterator.
It's either

for (std::vector<T>::const_reverse_iterator it=m_Coefficients.rbegin();      it!=m_Coefficients.rend();      ++it)


or

for (std::vector<T>::const_iterator it=m_Coefficients.begin();      it!=m_Coefficients.end();      ++it)
Yes, it worked when I used rbegin() and rend().

But now I have two questions stuck in my mind:

1) Do we use rbegin() and rend() just because end() points to a non-existing element, or is there other reasons?

2) In "for" statement, why do we use "++it", instead of "it++"?


Thanks in advance.
Oops, the problem still on.
Unfortunately std::vector::erase() does not accept reverse iterator.
What should I do now?
Quote:1) Do we use rbegin() and rend() just because end() points to a non-existing element, or is there other reasons?


Basically yes. You get off by one in the reverse iteration case, therfore there's reverse iterators and rbegin()/rend().


Quote:Original post by hkBattousai
2) In "for" statement, why do we use "++it", instead of "it++"?


Hit me.



About your remaining erase() problem, is it really mandatory that you iterate reverse?
Quote:Original post by hkBattousai
1) Do we use rbegin() and rend() just because end() points to a non-existing element, or is there other reasons?

It's so that we can use the same iteration semantics to move in the reverse direction as we use in the forward direction. Otherwise, there is no clean way of iterating in reverse using standard forward iterators. Just try to write such a loop and see for yourself :)

Quote:2) In "for" statement, why do we use "++it", instead of "it++"?

It's a remnant of the days when compilers weren't as good and would potentially generate a temporary iterator, but any modern compiler is smart enough to know when the temporary isn't needed. Choose whichever one you like better, unless you know your compiler doesn't make this optimization.

Quote:Unfortunately std::vector::erase() does not accept reverse iterator.

See this.
Quote:Original post by Zipster
Quote:Unfortunately std::vector::erase() does not accept reverse iterator.

See this.


I read this article, but I didn't understand anything from this statement:
&*(reverse_iterator(i)) == &*(i - 1)
Am I supposed to replace
m_Coefficients.erase(it);
with
m_Coefficients.erase(&*(it - 1));
or what?
Quote:Original post by Zipster
It's a remnant of the days when compilers weren't as good and would potentially generate a temporary iterator, but any modern compiler is smart enough to know when the temporary isn't needed. Choose whichever one you like better, unless you know your compiler doesn't make this optimization.


Compilers are still not smart enough to cover all cases. Think of the worst case where operator++ is implemented as a purely virtual function. Also, global optimization is still not in wide use, so not only the worst cases might be relevant.

Thing, it is less at the client side what counts, but actually inside the defininition of operator++() and operator++(int); if a non-void postfix operator++ is implemented, a temporary variable is mandatory to preserve the correct return value. The prefix version does not have to.

  • Therefore, the prefix version is at least as fast as the postfix version, but never slower.
  • Thus, the postfix version is at most as fast as the prefix version, but never faster.


Hence, I'd advise to use the postfix version only when you have to, i.e. when you need the value before it is incremented. But then again, this usually yields non-trivial to read code like if (foo_t foo=bar++), and possibly my advice is to never use the postfix version.
while ((m_Coefficients.back == static_cast<T>(0)) && (m_Coefficients.size() > 1)){	// I want the vector to have at least one element even if it is zero	m_Coefficients.pop_back();}

Isn't this code better?

This topic is closed to new replies.

Advertisement