Jump to content
  • Advertisement
Sign in to follow this  
hkBattousai

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

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

If you intended to correct an error in the post then please contact us.

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:
exception.png

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

Thanks.

(IDE: Visual Studio 2010)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
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 this post


Link to post
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++"?


Thanks in advance.

Share this post


Link to post
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 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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
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?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!