C++14:标准是否允许从 std::end() 中减去增量?
C++14: Does the standard allow subtracting a delta from std::end()?
我认为这个问题很容易解释。
如果我有 std::vector<int> v = {1,2,3}
,v.end() - 1
或 v.end()--
是有效的表达式吗?
我知道大多数迭代器都支持它,但问题是,它是定义的行为吗?不幸的是,很难找到有关它的信息。没有迭代器规范吗?标准本身似乎对此非常模糊,或者我只是错过了在如此低的水平上定义它们的段落。
例如看:http://www.cplusplus.com/reference/vector/vector/end/
"It does not point to any element, and thus shall not be dereferenced."
std::end() 显然不如 (v.begin() + 1) 通用,后者是最通用的,支持所有操作。所以这就引出了一个问题,哪些操作分别是 std::end() 和 std::begin() 的定义行为。
我需要这个来编写我自己的库。鉴于 v.end()--
是一个有效表达式,一些更高级的惰性求值迭代器很难编写,因为 "end" 在不遍历它或跟踪 "end" 的情况下并不知道迭代器本身使整体变得更加复杂,因为您需要对迭代器实现中的几乎所有内容进行特殊处理。
v.end()--
让我如此头疼的事实让我怀疑它是否被允许 ;)。不幸的是,由于频繁的使用模式,"end" 必须非常高效,所以它必须是恒定的时间,这就是让事情变得如此困难的原因。
迭代器以指针为模型。
指向范围的指针可以采用从指向第一个元素到指向最后一个元素的值。如果将指针移到该范围之外,则会(立即)发生未定义的行为。
End 基于 one-past-the-end 指针。您不能增加结束迭代器并获得定义的行为,也不能取消引用它,但除此之外它只是另一个迭代器。
Eric 的 "ranges v3" C++1z 提案包括非对称范围,其中开始迭代器的类型与结束迭代器的类型不同。这允许有效的 "null terminated string" 范围,其中你说 "start at this location, continue until you hit the null at the end" 编译为相当于手写 C 代码迭代。
找到证明这是真的证据很棘手,因为您要求的是不存在的证据:C++ 标准的任何部分都可以包含文本 "if you decrement the end iterator of a vector, the result is undefined",如果我引用标准的全部其余部分,除了那句话,如果你做了v.end()--
,它仍然是未定义的。但是,有一些示例,例如 Table 101,其中使用递减结束迭代器的副本。所以要么调用 back()
是未定义的行为,要么 end()
返回的迭代器副本可以递减。
有关当前标准草案的副本,请参阅 http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4431.pdf。对于您的问题,向量的结束迭代器的行为在任何 material 方面都没有改变。
我认为这个问题很容易解释。
如果我有 std::vector<int> v = {1,2,3}
,v.end() - 1
或 v.end()--
是有效的表达式吗?
我知道大多数迭代器都支持它,但问题是,它是定义的行为吗?不幸的是,很难找到有关它的信息。没有迭代器规范吗?标准本身似乎对此非常模糊,或者我只是错过了在如此低的水平上定义它们的段落。
例如看:http://www.cplusplus.com/reference/vector/vector/end/
"It does not point to any element, and thus shall not be dereferenced." std::end() 显然不如 (v.begin() + 1) 通用,后者是最通用的,支持所有操作。所以这就引出了一个问题,哪些操作分别是 std::end() 和 std::begin() 的定义行为。
我需要这个来编写我自己的库。鉴于 v.end()--
是一个有效表达式,一些更高级的惰性求值迭代器很难编写,因为 "end" 在不遍历它或跟踪 "end" 的情况下并不知道迭代器本身使整体变得更加复杂,因为您需要对迭代器实现中的几乎所有内容进行特殊处理。
v.end()--
让我如此头疼的事实让我怀疑它是否被允许 ;)。不幸的是,由于频繁的使用模式,"end" 必须非常高效,所以它必须是恒定的时间,这就是让事情变得如此困难的原因。
迭代器以指针为模型。
指向范围的指针可以采用从指向第一个元素到指向最后一个元素的值。如果将指针移到该范围之外,则会(立即)发生未定义的行为。
End 基于 one-past-the-end 指针。您不能增加结束迭代器并获得定义的行为,也不能取消引用它,但除此之外它只是另一个迭代器。
Eric 的 "ranges v3" C++1z 提案包括非对称范围,其中开始迭代器的类型与结束迭代器的类型不同。这允许有效的 "null terminated string" 范围,其中你说 "start at this location, continue until you hit the null at the end" 编译为相当于手写 C 代码迭代。
找到证明这是真的证据很棘手,因为您要求的是不存在的证据:C++ 标准的任何部分都可以包含文本 "if you decrement the end iterator of a vector, the result is undefined",如果我引用标准的全部其余部分,除了那句话,如果你做了v.end()--
,它仍然是未定义的。但是,有一些示例,例如 Table 101,其中使用递减结束迭代器的副本。所以要么调用 back()
是未定义的行为,要么 end()
返回的迭代器副本可以递减。
有关当前标准草案的副本,请参阅 http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4431.pdf。对于您的问题,向量的结束迭代器的行为在任何 material 方面都没有改变。