【问题标题】:c++: Is it valid to subtract an iterator from an element pointer to get a valid index?c ++:从元素指针中减去迭代器以获得有效索引是否有效?
【发布时间】:2022-01-01 23:04:43
【问题描述】:

我遇到了以下代码:

for (int i = 0; i < subspan.size(); i++) {
  ...
  int size = size_table[&(subspan[i]) - fullspan.begin()];
  ...
}

subspanfullspan都是std::span类型(实际上是absl::Span来自Google's Abseil library,但它们似乎与std::span几乎相同)并且是同一数据数组的视图( fullspan 跨越整个数组)。

这是有效且定义明确的代码吗?当- 运算符与 lhs 指针一起应用时,它似乎取决于迭代器被转换为相应的指针值。

【问题讨论】:

  • 视情况而定——因此您需要阅读文档才能找到答案。有几种可能性,取决于 absl::Span 是什么,.begin() 成员返回什么类型,&amp;(subspan[i]) 的结果是什么类型(例如,&amp; 是“地址”运算符,还是它导致调用一元 operator&amp;() 并返回其他内容?)
  • 我宁愿安全地通过&amp;*fullspan.begin() 确保两者都是相同类型的指针 - 或者立即对迭代器进行操作,任何不使用基于 for 循环的迭代器的理由 - 或甚至是基于范围的?
  • @Aconcagua 我不知道,不是我的代码。只是想了解它是否定义明确
  • @Aconcagua or operate on iterators right away 迭代器来自不同的跨度,所以我不认为它更安全;这更有可能编译,但如果迭代器类型验证范围,则可能在运行时失败。 &amp;*fullspan.begin() 可以假设跨度确实是同一个数组。

标签: c++ iterator abseil


【解决方案1】:

从元素指针中减去迭代器得到有效索引是否有效?

它可能是,这取决于迭代器是如何定义的。例如,如果迭代器是同类型的指针,并且指向同一个数组的元素,它就可以工作。

但是,没有通用迭代器概念指定此类操作,因此不能保证此类操作适用于任何标准迭代器。因此,它不是一个可移植的假设,即它可以在通用代码中工作。

这是有效且定义明确的代码吗?

所讨论的迭代器类型被定义为指针类型,因此满足该条件。 Abseil 既没有完整的文档记录也没有详细说明,因此很难说这是一个有意的功能,还是附带的实现细节。如果是后者,那么代码可能会在 Abseil 的未来版本中中断。

【讨论】:

    【解决方案2】:

    阅读the implementation of absl::Span,我们有:

    template <typename T>
    class Span {
    ...
     public:
      using element_type = T;
      using pointer = T*;
      using const_pointer = const T*;
      using reference = T&;
    ...
      using iterator = pointer;
    ...
      constexpr iterator begin() const noexcept { return data(); }
      constexpr reference operator[](size_type i) const noexcept { return *(data() + i); }
    ...
    }
    

    所以你的表达式归结为简单的指针算术。 请注意,没有检查两个跨度是否引用相同的基本跨度,但您断言不是这种情况。

    【讨论】:

    • 我不会依赖实现来告诉你这一点。应该记录这是否是一个安全的假设。
    猜你喜欢
    • 2020-01-16
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多