矢量`s结束迭代器内容

时间:2013-11-02 17:33:28

标签: c++ stl iterator

关于以下示例,我有两个问题: 1)

std::vector<int> v(5,1);
cout << *v.end();

打印结果是否未定义(取决于编译器)

2)

int x = 5,y = 6;
std::vector<int*> pv;
pv.push_back(&x);
pv.push_back(&y);
cout << *pv.end();

打印结果是否未定义(取决于编译器)或NULL

6 个答案:

答案 0 :(得分:3)

end()处没有项目,它是向量中最后一个有效项目之后的迭代器。

*v.end();

未定义的行为 。您可以使用end()来比较迭代器是否指向最后一项之后的项目。

访问上一项值的简便方法是back(),例如:

cout << v.back();

答案 1 :(得分:2)

end()迭代器指向一个位置,该位置是容器的最后一个元素之后的元素。访问它指向的数据将调用未定义的行为,这两个示例都是这种情况。

答案 2 :(得分:1)

如果我们查看草案C ++标准部分24.21 迭代器要求,那么结束时取消引用可能会结束很糟糕,但看起来它是实现已定义 >然后转到24.2.1 一般 5 说(强调我的):

  

正如指向数组的常规指针一样,保证指针值指向数组的最后一个元素,因此对于任何迭代器类型,都有一个迭代器值指向相应序列的最后一个元素。这些值称为past-the-end值。 定义表达式 i的迭代器i的值称为可解除引用。库从不假设过去的值是可解除引用的。 迭代器也可以具有与任何序列无关的奇异值。 [示例:在声明未初始化的指针x(与int x;)之后,必须始终假定x具有指针的奇异值。 -end example] 对于奇异值,大多数表达式的结果都是未定义的; [...] 可解除引用的值始终是非单数的。

答案 3 :(得分:1)

首先,在这两种情况下,行为都是未定义的。注意,这不是未定义的“打印结果”。您的代码甚至没有机会打印任何东西。仅仅*运算符应用于结束迭代器已经导致未定义的行为。例如。仅此一点

*v.end();

已经是未定义的行为。

其次,在这种情况下未定义并不意味着“取决于编译器”。 实现定义的行为取决于编译器。 未定义表示“完全不可预测”,即使您使用的是相同的编译器。

P.S。在标准委员会中似乎有一些正在进行的工作,需要注意一些密切相关的问题。

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#208

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1213

希望它能够更清晰地说明什么是合法的,什么不适合过去的迭代器。但很明显,在一般情况下,past-the-end迭代器在法律上可以是一个单一的迭代器,这意味着在一般情况下它可以是不可解除引用的。

答案 4 :(得分:0)

是的,这两个都是未定义的。

答案 5 :(得分:0)

vector::end - 将迭代器返回到end(公共成员函数)

您可以阅读更多here


第一个例子

    std::vector<int> v(5,1);
    cout << *(v.end()-1);

未定义(查看图片),v.end()指向最后一个元素后的地址,如果容器为空,则此函数返回与{{1}相同的地址}。 enter image description here

您的第二个例子

v.begin()