我有一些代码可以移除std::vector
中的某些元素:
splitVector.erase(splitVector.begin());
if ( (splitVector.end())->length() == 0 )
splitVector.erase(splitVector.end());
此代码在MacOs上运行正常但在Windows上它只是给我这个错误:
Expression:vector iterator not deferencable
我不明白为什么这个操作适用于一个操作系统并且在其他操作系统上给出错误,因为它非常基本。
任何人都知道为什么会这样?
我还应该继续使用std::vector
还是转移到其中一个升级容器?
由于
答案 0 :(得分:5)
你需要意识到vector :: end不是向量中的最后一项。这是最后一项之后的一个。如果您尝试取消引用它,那么您的程序将被窃听。 Windows有助于告诉你这一点,MacOS没有帮助。建议您阅读有关如何在标准库中使用容器和迭代器的内容。如果您不了解基础知识,那么转向提升不太可能对您有所帮助。
也许你想要做的就是这个
if ((splitVector.end() - 1)->length() == 0)
splitVector.erase(splitVector.end() - 1);
答案 1 :(得分:4)
if ( (splitVector.end())->length() == 0 )
这只是调用未定义的行为(UB),因为iterator
返回的end()
不能解除引用。
它在一个平台上工作而不在另一个平台上工作正是因为它的UB意味着任何事情都可能发生;存在无限多种可能性,并且它们都不受语言规范的保证。
此外,splitVector.end()
不是 last 元素的迭代器。它的 past-the-last-element 迭代器。你真正想要的是这个:
splitVector.erase(splitVector.begin());
if(!splitVector.empty() && (splitVector.begin() + splitVector.size()-1 )->length() == 0 )
splitVector.erase(splitVector.begin() + splitVector.size() - 1);
答案 2 :(得分:4)
像std::vector<T>
这样的容器定义半开范围,即end()
迭代器指向后面的内存最后一个元素。这意味着,没有可怜的对象。
你想做的可能是
if (!splitVector.empty() && splitVector.back().empty())
splitVector.pop_back();
注意在访问元素之前对非空向量的额外测试。
答案 3 :(得分:2)
有两个错误,一个在很大程度上被评论过:
vector.end()->foo()
调用未定义的行为。
另一个更具间接性:
vector.erase(vector.begin());
在erase
迭代器上调用end
(UB)是错误的,如果vector
为空,那么则为vector.begin() == vector.end()
,调用UB。
此错误再次出现在if
的正文中。
据我所知,你所寻找的东西如下:
if (!vector.empty()) { vector.pop_front(); }
if (!vector.empty() && vector.back().length == 0) { vector.pop_back(); }
请注意vector
上存在惯用方法,这些方法允许您不要使用这些笨拙的向量,并且还要注意这里使用的方法需要非空向量才能工作。