我编写了一个简短的代码,使用while循环遍历(排序!)结构向量并根据其价格插入新元素(如果已经有特定价格的条目,新条目应该插入现有条目后面。
使用g++
和Sublime Text 3一切正常(在本问题末尾输出),但使用Visual Studio 2015我收到错误:Debug Assertion Failed! ... Expression: vector iterator not dereferencable
。 (请注意,如果新元素应附加在现有向量的末尾,则此错误仅会出现,如果我们将新元素更改为struc newEl = {5, 2.0}
,则VS和g++
都可以正常工作。
代码如下所示:
#include <iostream>
#include <vector>
struct struc {
int num;
double price;
};
int main() {
std::vector<struc> v = { { 1, 1.5 },{ 2, 1.6 },{ 3, 2 },{ 4, 2.6 } };
struc newEl = { 5, 2.7 };
std::vector<struc>::iterator it = v.begin();
while (((*it).price <= newEl.price) && (it < v.end())) {
it++;
}
v.insert(it, newEl);
for (struc vec : v) {
std::cout << vec.num << ", " << vec.price << std::endl;
}
std::cout << "Finished";
return 0;
}
输出应该是(并且在g++
和ST的情况下):
1, 1.5
2, 1.6
3, 2
4, 2.6
5, 2.7
Finished
现在我的问题是,导致VS中的错误的原因是什么?我需要更改它以使其在VS中工作?
非常感谢!
答案 0 :(得分:6)
while (((*it).price <= newEl.price) && (it < v.end())) {
你需要检查你是否在结束之前取消引用迭代器并检查值:
while ( (it!=v.end()) && (it->price <= newEl.price)) {
否则你基本上保证你会取消引用end
迭代器,这正是你想要避免的。
(你不能在大多数类型的迭代器上使用<
,所以用!=
检查循环是一种更常见的做法。)
您可能知道&&
&#34;短路&#34;所以,如果第一个条件是false
,那么第二个条件甚至不会被检查。这是由语言保证的(除非一些白痴超载operator&&
,但幸运的是,这很少见,因为这是一个糟糕的主意)。这就是为什么我的版本是安全的。
现在,这个错误会触发Undefined Behaviour - 错误就在你身上!这种语言甚至不会帮助你,任何事情都可能发生。您的程序可能崩溃,它可能看起来正常工作,它可能每隔一段时间工作,或者它可以将您的笔记本电脑变成粉红色的长颈鹿。 C ++交易对你来说很快就会很快。
我知道Microsoft的实现,在调试模式下,checked iterators在这里抓住你的错误,代价是总是检查。在发布模式下,这不会发生。
我没有使用它,但根据this answer,GCC确实有类似的东西。
(顺便说一句,我真的认为使用std::endl
是不好的做法。Here's why。有些人不同意我的意见。我想,了解它并做出自己的决定。 )