gpt4 book ai didi

c++ - 是否允许 std::string 的 end+1 迭代器?

转载 作者:IT老高 更新时间:2023-10-28 21:47:46 27 4
gpt4 key购买 nike

创建到end(str)+1 的迭代器是否有效?对于 std::string ?
如果不是,为什么不是?

这个问题仅限于 C++11 及更高版本,因为在 C++11 之前,数据已经存储在一个连续 block 中 以这种方式存储。
我认为这可能会有所不同。

std::string 之间的显着差异和我推测的任何其他标准容器是它总是包含比它的 size 多一个元素。 ,零终止符,以满足 .c_str() 的要求.

21.4.7.1 basic_string accessors [string.accessors]

const charT* c_str() const noexcept;
const charT* data() const noexcept;

1 Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
2 Complexity: Constant time.
3 Requires: The program shall not alter any of the values stored in the character array.

尽管如此,即使它应该恕我直言,保证所述表达式是有效的,为了与零终止字符串的一致性和互操作性,如果没有别的,我发现的唯一一段对此表示怀疑:

21.4.1 basic_string general requirements [string.require]

4 The char-like objects in a basic_string object shall be stored contiguously. That is, for any basic_string object s, the identity &*(s.begin() + n) == &*s.begin() + n shall hold for all values of n such that 0 <= n < s.size().

(所有引用均来自 C++14 最终草案 (n3936)。)

相关:Legal to overwrite std::string's null terminator?

最佳答案

TL;DR: s.end() + 1是未定义的行为。


std::string是一种奇怪的野兽,主要是出于历史原因:

  1. 它试图带来 C 兼容性,已知额外的 \0字符存在超出 strlen 报告的长度.
  2. 它采用基于索引的界面设计。
  3. 事后想到,在标准库中与其他 STL 代码合并时,添加了一个基于迭代器的接口(interface)。

这导致了std::string ,在 C++03 中,编号为 103 member functions ,然后又添加了一些。

因此,应该预料到不同方法之间的差异。


已经在基于索引的界面中出现了差异:

§21.4.5 [string.access]

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

1/ Requires: pos <= size()

const_reference at(size_type pos) const;reference at(size_type pos);

5/ Throws: out_of_range if pos >= size()

是的,你没看错,s[s.size()]返回对 NUL 字符的引用,而 s.at(s.size())抛出 out_of_range异常(exception)。如果有人告诉你替换所有使用 operator[]at因为它们更安全,所以要小心 string陷阱……


那么,迭代器呢?

§21.4.3 [string.iterators]

iterator end() noexcept;
const_iterator end() const noexcept;
const_iterator cend() const noexcept;

2/ Returns: An iterator which is the past-the-end value.

非常平淡。

所以我们必须引用其他段落。指针由

提供

§21.4 [basic.string]

3/ The iterators supported by basic_string are random access iterators (24.2.7).

§17.6 [requirements] 似乎没有任何相关内容。因此,字符串迭代器只是普通的旧迭代器(您可能会感觉到这是怎么回事......但是既然我们已经走到了这一步,让我们一路走下去)。

这导致我们:

24.2.1 [iterator.requirements.general]

5/ Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence. These values are called past-the-end values. 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. [...]

所以,*s.end()格式不正确。

24.2.3 [input.iterators]

2/ Table 107 -- Input iterator requirements (in addition to Iterator)

++r 的前置条件列表和 r++r可以取消引用。

Forward 迭代器、Bidirectional 迭代器和 Random 迭代器都没有解除这个限制(并且都表明它们继承了其前身的限制)。

此外,为了完整起见,在 24.2.7 [random.access.iterators] 中,表 111 -- 随机访问迭代器要求(除了双向迭代器) 列出以下操作语义:

  • r += n等价于 [inc|dec]rememting r n
  • a + nn + a相当于复制a然后申请 += n到拷贝

同样适用于 -= n- n .

因此 s.end() + 1是未定义的行为。

关于c++ - 是否允许 std::string 的 end+1 迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33657050/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com