C ++ 14:标准是否允许从std :: end()中减去delta?

时间:2015-06-26 17:29:16

标签: c++11 iterator c++-standard-library

我认为这个问题非常自我解释。

如果我有std::vector<int> v = {1,2,3},有v.end() - 1v.end()--个有效表达式吗?

我知道大多数迭代器都支持它,但问题是,它是否定义了行为?不幸的是,很难找到有关它的信息。是不是有迭代器规范?标准本身似乎非常模糊,或者我只是错过了在如此低的水平上定义它们的段落。

例如,请查看:http://www.cplusplus.com/reference/vector/vector/end/

“它不指向任何元素,因此不得解除引用。” std :: end()显然比(v.begin()+ 1)更通用,这是最常用的并且支持所有操作。所以这引出了一个问题,哪些操作分别为std :: end()和std :: begin()定义了行为。

我需要这个来编写我自己的库。一些更高级的惰性求值迭代器很难在v.end()--作为有效表达式的情况下编写,因为如果没有迭代它或者跟踪迭代器本身内的“结束”,那么“结束”并不是真正知道的。整个很复杂,因为你需要在迭代器实现中几乎所有的特殊情况。

v.end()--导致我头疼的事实使我想知道它是否被允许;)。不幸的是,由于频繁的使用模式,“结束”必须非常高效,因此它必须是恒定的时间,这就是使这里的事情变得如此困难的原因。

1 个答案:

答案 0 :(得分:1)

迭代器以指针为模型。

指向范围的指针可以从指向第一个元素获取值,指向一个过去一个元素。如果将指针移到该范围之外,则会立即发生未定义的行为。

结束基于一个接一个的结束指针。你不能增加结束迭代器并获得定义的行为,你不能取消引用它,但除此之外它只是另一个迭代器。

Eric&#34;范围v3&#34; C ++ 1z的提议包括非对称范围,其中begin迭代器的类型与end迭代器的类型不同。这允许有效的&#34;空终止字符串&#34;范围,你说&#34;从这个位置开始,继续直到你在结束时达到空值&#34;它编译成等同于手写的C代码迭代。

找到证明这是真的很棘手,因为你要求缺席的证据:C ++标准的任何部分都可以包含文本&#34;如果你递减向量的结束迭代器,结果是未定义的&# 34;,如果我引用除该句子之外的整个标准的其余部分,如果你v.end()--,它仍然是未定义的。但是,有一些示例,例如表101,其中使用了减少结束迭代器的副本。因此,调用back()是未定义的行为,或者end()返回的迭代器的副本可以递减。

请参阅http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4431.pdf以获取当前草案标准的副本。向量的结束迭代器的行为没有以任何重要方式改变你的问题。