【问题标题】:Is it possible for a C++ iterator to have gaps and not be linear?C++ 迭代器是否有可能存在间隙而不是线性的?
【发布时间】:2021-12-20 10:40:18
【问题描述】:

我编写了一个 C++ 迭代器来遍历 std::string,它是 UTF-8。

这个想法是让迭代器返回char32_t 字符而不是字节。迭代器可用于前进或后退。我也可以倒带,我想相当于rbegin()

由于一个字符可以跨越多个字节,我在 std::string 中的位置可能跳跃 2、3 或 4 个字节(如果遇到无效字符,库将抛出)。

这也意味着到某个字符的距离并不总是一一递增。换句话说,++it 可以将位置增加一个从 1 到 4 的数字,--it 以类似的方式反向减去。

这是 C++ 迭代器的预期/合法行为吗?

【问题讨论】:

  • 正如您所描述的,只要“位置”不可访问(是私有的),就没有“间隙”或“非线性”,因此作为双向迭代器显然没有问题。但是,它可能不能是 RandomAccessIterator。
  • 另外,也许看看 Qt 中的 QString 如何处理 UTF 字符作为另一个例子。使用 QString,字符数据在访问器函数中被另一个类封装,而不是提供对底层数据的直接访问。
  • @Remarkod QString 处理 UTF-16 并且它们不能正确处理代理项(即它们为字符返回 unsigned short)。不过,也许 Qt v6 会增强这部分。所以实际上他们可以管理unsigned short的数组。
  • 双向迭代器就是这样做的。想想std::map,它是一个RB树,所以迭代可以跳过整个分支。
  • 是的,这正是迭代器的用途:为可能不统一的数据结构提供统一。

标签: c++ iterator


【解决方案1】:

除了迭代器之外,C++ 中的许多算法在使用普通指针时同样可以很好地工作。 std::copy 可以使用普通指针,很好。 std::find_if 也会很高兴。以此类推。

幸运的是,std::copy 在您提供给它的指针上调用 ++ 运算符。好吧,你猜怎么着?将一堆int *s 传递给std::copy 会导致实际指针增加sizeof(int),而不是1。

std::copy 不在乎。

迭代器的属性及其要求是根据逻辑结果逻辑效果定义的各种运算符导致发生的事情(以及哪些运算符对给定的迭代器有效)。迭代器的内部实现是否将内部值(以某种方式表示迭代器)增加 1、2、4 或 42 是无关紧要的。请注意,反向迭代器会导致实际内部指针因++ 运算符重载而递减

如果您的自定义迭代器实现的 ++--*[]++- 运算符(无论哪个适合您的迭代器)满足其分配的所有要求迭代器类别,那么这些运算符对代表您的迭代器的实际原始指针值的实际影响是无关紧要的。

假设您的自定义迭代器是随机访问迭代器,您的问题的答案如下:如果所有必需的运算符重载都满足随机访问迭代器的所有要求,那么对底层指针值的实际影响是无关紧要的。

这同样适用于任何迭代器类别,而不仅仅是随机访问。

【讨论】:

  • 此时,我没有实现[] 运算符,因为它只是双向的,而不是随机的。可以实现[],但这会很昂贵(您必须从头开始解析整个字符串才能找到位置)。
  • 不可能按照 OP 描述的方式实现 legacyrandomaccess 迭代器。这些问题并非微不足道,这个答案并没有解决它们。
猜你喜欢
  • 2020-01-16
  • 2014-09-06
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 2015-12-23
  • 2018-10-01
  • 1970-01-01
相关资源
最近更新 更多