Where in the standard to I read or deduce that vector<T>::operator[] invokes UB for out-of-bound input?

huangapple go评论75阅读模式
英文:

Where in the standard to I read or deduce that vector<T>::operator[] invokes UB for out-of-bound input?

问题

cppreference上,我读到关于std::vector&lt;T,Allocator&gt;::operator[]的以下内容:

> 通过这个运算符访问不存在的元素是未定义行为。

标准草案中是否包含类似的句子?或者,我应该从标准的哪个部分推断出这一点?

我猜如果标准没有提及,那就会造成未定义行为。但我也没有找到关于std::vector&lt;T,Allocator&gt;::at的任何信息,所以...

英文:

On cppreference, I read the following about std::vector&lt;T,Allocator&gt;::operator[]:

> Accessing a nonexistent element through this operator is undefined behavior.

Does the standard draft contain a similar sentence? Or, what part of the standard should I deduce this thing from?

I guess that if the standard says nothing about it, that would make it UB. But I haven't found anything about std::vector&lt;T,Allocator&gt;::at either, so...

答案1

得分: 5

这部分内容的翻译如下:

  • 它以一种非常迂回的方式进行了指定。

  • 首先,成员未直接针对vector指定,而是针对通用的Sequence。您可以在这里找到规范:http://eel.is/c++draft/sequence.reqmts。

  • 首先,明显的部分是:at有以下条款:http://eel.is/c++draft/sequence.reqmts#123

    抛出: 如果n >= a.size(),则抛出out_of_range异常。
    这就是at的行为来源。

  • 至于[],它说:

    返回: *(a.begin() + n)
    因此,效果与该表达式相同。我们需要遵循这一点,以找到未定义行为。为此,我们需要查看迭代器要求

  • 现在,C++20的要求几乎难以阅读,但C++17的要求仍然存在且适用。因此:

    • http://eel.is/c++draft/iterator.requirements#random.access.iterators-1 表明a + n(对于某个迭代器a和差异n)意味着对a的副本tmp执行tmp += n
    • 同一位置指出,r += n 意味着重复应用 ++r(或者如果n为负数,则是 --r)。
    • 在http://eel.is/c++draft/iterator.requirements#tab:inputiterator中,我们了解到++r*a都有先决条件,即ra必须是可解引用的。请注意,在C++标准中违反先决条件会导致未定义行为。

这是非常复杂的部分。在这一点上,我们需要将vector::beginvector::end的规范组合在一起,以了解重复递增v.begin()将最终(即,在应用了v.size()次后)生成v.end(),它被指定为超出结尾迭代器。我找不到明确说明这些迭代器不可解引用的陈述,但是http://eel.is/c++draft/iterator.requirements#general-7规定标准库假定它们不能解引用,并且在vector的情况下确实如此。

因此,v[v.size()]等同于*(v.begin() + v.size()),等同于*v.end(),这是未定义行为。

v[v.size()+1]等同于*(v.begin() + v.size() + 1),等同于*std::next(v.end()),这是增加超出结尾迭代器,因此也是未定义行为。

英文:

It's specified in a very roundabout way.

First, the members aren't specified for vector directly, but instead for the general Sequence. You can find the specification here: http://eel.is/c++draft/sequence.reqmts.

First, the obvious part: at has the clause

> Throws: out_of_range if n &gt;= a.size().

So this is where at's behavior comes from.

As for [], it says:

> Returns: *(a.begin() + n)

So the effect is the same as of that expression. We need to follow this to find the undefined behavior. For that we need to look at the iterator requirements.

Now the C++20 requirements are nigh-unreadable, but the C++17 requirements are still there and do apply. So:

This is where it gets really complicated. At this point we need to piece together the specifications of vector::begin and vector::end to understand that repeated incrementing of v.begin() will eventually (as in, after v.size() applications) yield v.end(), which is specified to be the past-the-end iterator. I cannot find the explicit statement that such iterators are not dereferenceable, but http://eel.is/c++draft/iterator.requirements#general-7 specifies that the standard library assumes they are not, and in vector's case this is true.

Therefore, v[v.size()] is equivalent to *(v.begin() + v.size()), which is equivalent to *v.end(), which is undefined behavior.

And v[v.size()+1] is equivalent to *(v.begin() + v.size() + 1), which is equivalent to *std::next(v.end()), which is incrementing the past-the-end iterator and thus undefined behavior.

答案2

得分: 1

v[n] 等同于 *(v.begin() + n),根据 sequence.reqmts

如果迭代器不在范围内,它就不可解引用,这意味着 v[n] 是未定义行为,根据 iterator.requirements.general

对于迭代器 i,使得表达式 *i 被定义的值称为可解引用的库永远不会假设超出末尾的值是可解引用的。

英文:

First note that v[n] is equivalent to *(v.begin() + n) as per sequence.reqmts.

Now, if the iterator is not within the range, it is not derefereceble meaning v[n] is undefined behavior as per iterator.requirements.general:

> Values of an iterator i for which the expression *i is defined are called dereferenceable. The library never assumes that past-the-end values are dereferenceable.

huangapple
  • 本文由 发表于 2023年5月17日 15:00:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76269324.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定