Problem with a deferencable iterator only with visual studio 2010
I have this bit of code to remove certain开发者_JAVA百科 element in my std::vector
:
splitVector.erase(splitVector.begin());
if ( (splitVector.end())->length() == 0 )
splitVector.erase(splitVector.end());
This code works fine on MacOs but on windows it just give me this error :
Expression: vector iterator not deferencable
I don't understand why this operation works for one os and gives error on other since it's pretty basic.
Anyone has any idea why this occurs?
Also should I still keep using std::vector
or move to one of the boost container ?
Thanks
You need to realise that vector::end is not the last item in the vector. It's one past the last item. If you try to dereference it then your program is bugged. Windows is helpfully telling you this, MacOS unhelpfully didn't. Suggest you read up on how to use containers and iterators in the standard library. If you don't understand the basics then moving to boost is unlikely to help you.
Perhaps what you were trying to do is this
if ((splitVector.end() - 1)->length() == 0)
splitVector.erase(splitVector.end() - 1);
Containers like std::vector<T>
define half-open ranges, i.e. the end()
iterator points to memory behind the last element. It means, there is no deferencable object.
What you want to do is probably
if (!splitVector.empty() && splitVector.back().empty())
splitVector.pop_back();
Note the extra test for non-empty vector before accessing elements.
if ( (splitVector.end())->length() == 0 )
This simply invokes undefined behavior (UB), because iterator
returned by end()
is not dereferenceable.
It works on one platform and not on other is precisely because its UB which means anything can happen; there are infinite number of possibilities, and none of them is guaranteed by the language specification.
Also, splitVector.end()
is not an iterator to the last element. Its past-the-last-element iterator. What you actually want is this:
splitVector.erase(splitVector.begin());
if(!splitVector.empty() && (splitVector.begin() + splitVector.size()-1 )->length() == 0 )
splitVector.erase(splitVector.begin() + splitVector.size() - 1);
There are two mistakes, one has been largely commented on:
vector.end()->foo()
Invokes Undefined Behavior.
The other is more circumstantial:
vector.erase(vector.begin());
It is an error to call erase
(UB) on the end
iterator, and if the vector
is empty then vector.begin() == vector.end()
, invoking UB.
This error once again appears in the body of the if
.
As far as I can tell, what you are looking for looks something like:
if (!vector.empty()) { vector.pop_front(); }
if (!vector.empty() && vector.back().length == 0) { vector.pop_back(); }
Note that there are idiomatic methods on vector
which allow you no to fiddle with those awkward vectors, and also note that those used here require a non-empty vector to work.
精彩评论