调试断言失败了visual studio 2015:矢量迭代器不是dereferencable

Dav*_*vid 3 c++ visual-studio-2015

我编写了一个简短的代码,使用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;
}
Run Code Online (Sandbox Code Playgroud)

输出应该是(并且在g++和ST 的情况下):

1, 1.5
2, 1.6
3, 2
4, 2.6
5, 2.7
Finished
Run Code Online (Sandbox Code Playgroud)

现在我的问题是,导致VS中的错误的原因是什么,我需要更改以使其在VS中工作?

非常感谢你!

BoB*_*ish 6

while (((*it).price <= newEl.price) && (it < v.end())) {
Run Code Online (Sandbox Code Playgroud)

取消引用迭代器并检查值之前,您需要检查是否在最后:

while ( (it!=v.end()) && (it->price <= newEl.price)) {
Run Code Online (Sandbox Code Playgroud)

否则,您基本上保证您将取消引用end迭代器,这正是您要避免的.

(你不能<在大多数类型的迭代器上使用,所以检查循环!=是一种更常见的做法).

您可能会注意到&&"短路",因此,如果第一个条件是false,则第二个条件甚至不会被检查.这是由语言保证的(除非一些白痴超载operator&&,但幸好这种情况很少见,因为这是一个坏主意).这就是我的版本安全的原因.

现在,这个错误触发了未定义的行为 - 错误就在你身上!这种语言甚至不会试图帮助你,任何事情都可能发生.您的程序可能崩溃,它可能看起来正常工作,它可能每隔一段时间工作,或者它可以将您的笔记本电脑变成粉红色的长颈鹿.C++交易对你很快就很好.

我知道Microsoft的实现,在调试模式下,检查了在这里捕获你的错误的迭代器,代价是总是检查.在发布模式下,这不会发生.

我没有用它,但根据这个答案,GCC确实有类似的东西.


(顺便说一句,我真的认为使用std::endl是不好的做法.这就是为什么.有些人不同意我的意见.我想,了解它并做出自己的决定.)