【问题标题】:C++14: Does the standard allow subtracting a delta from std::end()?C++14:标准是否允许从 std::end() 中减去增量?
【发布时间】:2015-09-13 17:54:55
【问题描述】:

我认为这个问题很容易解释。

如果我有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()-- 让我头疼的事实让我怀疑它是否被允许;)。不幸的是,由于频繁的使用模式,“结束”必须非常有效,所以它必须是恒定的时间,这就是让事情变得如此困难的原因。

【问题讨论】:

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


    【解决方案1】:

    迭代器是根据指针建模的。

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

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

    Eric 针对 C++1z 的“ranges v3”提案包括非对称范围,其中开始迭代器的类型与结束迭代器的类型不同。这允许有效的“空终止字符串”范围,您说“从这个位置开始,继续直到你在结尾处遇到空”,这编译成相当于手写 C 代码迭代。

    找到证明这是真的证据很棘手,因为您要求提供不存在的证据:C++ 标准的任何部分都可以包含文本“如果减少向量的结束迭代器,则结果未定义”,如果我引用了标准的其余部分,除了那句话,如果你做了v.end()--,它仍然是未定义的。但是,也有一些示例,例如表 101,其中使用了递减结束迭代器的副本。因此,要么调用back() 是未定义的行为,要么可以减少end() 返回的迭代器的副本。

    有关当前草案标准的副本,请参阅 http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4431.pdf。对于您的问题,向量的结束迭代器的行为没有以任何实质性方式改变。

    【讨论】:

    • v.end()-- 仅在迭代器不是指针时才有效。讨厌的内置 -- 需要一个左值操作数。
    • 另外,[bidirectional.iterators] 中的表 110 说 --r 的唯一前提是“存在 s 使得 r == ++s。”
    • 我喜欢你的回答;)。再给我一些时间来充分处理它。但通常空终止问题是我在这里遇到的问题的一个简单模型。假设您有那些不对称的范围并且想要执行 std::end()--,那么实际上,迭代器需要扫描空终止并在 NULL 之前给您返回元素的迭代器。这是可能的,但不是恒定的时间,并且搞砸了您可以为用户提供的复杂性保证。这正是我的问题,只是我的涉及更复杂的数据结构,但在这种情况下没关系。
    • 同时在生成序列上执行 std::end()-- 将进入无限循环 :D。作为一个极端的例子。这就是为什么它们应该只能向前迭代。
    • 关于非对称范围的另一个很酷的事情是,您可以区别对待 std::end() 和 "std::begin() + size"。在后一种情况下,您知道 NULL 在字符串中的位置,因为您实际上是从头开始迭代它,所以从结尾减去是常数时间。但是在很多情况下,从 std::end() 中减去永远不可能是常数时间。
    猜你喜欢
    • 2016-02-12
    • 2019-02-04
    • 2016-07-31
    • 1970-01-01
    • 2011-09-17
    • 2018-12-07
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    相关资源
    最近更新 更多