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

This topic is 2891 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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:

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

Thanks.

(IDE: Visual Studio 2010)

##### Share on other sites
If you want to iterate over the vector in reverse order, you need to use rbegin() and rend(). end() is never a dereferencable iterator.

##### Share on other sites
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)

##### Share on other sites
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++"?

##### Share on other sites
Oops, the problem still on.
Unfortunately std::vector::erase() does not accept reverse iterator.
What should I do now?

##### Share on other sites
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 hkBattousai2) 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?

##### Share on other sites
Quote:
 Original post by hkBattousai1) 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.

##### Share on other sites
Quote:
Original post by Zipster
Quote:
 Unfortunately std::vector::erase() does not accept reverse iterator.

See this.

&*(reverse_iterator(i)) == &*(i - 1)
Am I supposed to replace
m_Coefficients.erase(it);
with
m_Coefficients.erase(&*(it - 1));
or what?

##### Share on other sites
Quote:
 Original post by ZipsterIt'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.

##### Share on other sites
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?

1. 1
2. 2
3. 3
Rutin
24
4. 4
5. 5
khawk
14

• 11
• 11
• 23
• 10
• 9
• ### Forum Statistics

• Total Topics
633651
• Total Posts
3013128
×