简体   繁体   English

仅Visual Studio 2010的可延迟迭代器存在问题

[英]Problem with a deferencable iterator only with visual studio 2010

I have this bit of code to remove certain element in my std::vector : 我有这段代码来删除我的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 : 这段代码在MacO上运行良好,但在Windows上却给了我这个错误:

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 ? 还应该继续使用std::vector还是移至boost容器之一?

Thanks 谢谢

You need to realise that vector::end is not the last item in the vector. 您需要认识到vector :: end不是向量中的最后一项。 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. Windows会告诉您有关信息,而MacOS则没有帮助。 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);
  if ( (splitVector.end())->length() == 0 )

This simply invokes undefined behavior (UB), because iterator returned by end() is not dereferenceable. 这只是调用未定义的行为(UB),因为end()返回的iterator是不可引用的。

It works on one platform and not on other is precisely because its UB which means anything can happen; 它可以在一个平台上工作,而不能在另一个平台上工作,正是因为它的UB意味着一切皆有可能。 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. 同样, splitVector.end()也不是最后一个元素的迭代器。 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);

Containers like std::vector<T> define half-open ranges, ie the end() iterator points to memory behind the last element. std::vector<T>这样的容器定义了半开范围,即end()迭代器指向最后一个元素后面的内存。 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. 在访问元素之前,请注意对非空向量的额外测试。

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. end迭代器上调用erase (UB)是错误的,并且如果vector为空,vector.begin() == vector.end() ,调用UB。

This error once again appears in the body of the if . 该错误再次出现在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. 请注意, vector上有惯用的方法,您不能随意使用那些笨拙的矢量,并且还要注意,此处使用的方法需要非空矢量才能工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM