【问题标题】:Is one-past-end pointer OK for non-array object types?非数组对象类型的单过去指针可以吗?
【发布时间】:2019-11-30 15:26:23
【问题描述】:

这是有效的 C++ 吗?

int main()
{
    int i = 0;
    int* pi = &i;
    ++pi;
}

我知道数组类型允许使用过去结束的指针,但在这种情况下我不确定。该代码在技术上是否具有未定义的行为?

【问题讨论】:

    标签: c++ pointers language-lawyer pointer-arithmetic


    【解决方案1】:

    是的,没关系。它是任何指针类型可能包含的四类值之一。

    [basic.compound](强调我的)

    3每个指针类型的值都是以下之一:

    • 指向对象或函数的指针(据说该指针指向对象或函数),或
    • 超过对象末尾的指针 ([expr.add]),或
    • 该类型的空指针值 ([conv.ptr]),或
    • 一个无效的指针值。

    一个指针类型的值,它是一个指向或超过一个指针结尾的指针 object 表示内存中第一个字节的地址 ([intro.memory]) 对象或内存中的第一个字节占用 结束后对象分别占用的存储空间。 [ 注意:超过对象末尾的指针 ([expr.add]) 不是 被认为指向对象类型的不相关对象 可能位于该地址。指针值在以下情况下变为无效 它表示的存储达到其存储期限的结束;看 [基本.stc]。 — 尾注 ] 用于指针算术 ([expr.add]) 和比较 ([expr.rel], [expr.eq]),指针过去 考虑 n 个元素的数组 x 的最后一个元素的结尾 等效于指向 x 的假设数组元素 n 的指针 一个不是数组元素的类型 T 的对象被认为是 属于具有一个 T 类型元素的数组。

    如您所见,此处还提到了数组类型,它们的假设对象位于末尾。正如footnote in [expr.add] 解释的那样,获得一个过去指针的算法意味着也是有效的:

    如 [basic.compound] 中所述,为此目的,非数组元素的对象被认为属于单元素数组,并且超过 n 个元素数组的最后一个元素的指针被认为是为此,它相当于一个指向假设数组元素 n 的指针。

    【讨论】:

    • @LightnessRaceswithMonica - 脚注虽然不规范,但暗示没关系eel.is/c++draft/expr.add#footnote-77 - 我认为你在编辑问题上是对的
    • 既然“无效的指针值”在这里也是一个范畴,那么pi += 2 也可以吗?如果不是,为什么?
    • @Ayxan - 当占用存储空间的对象达到其生命周期结束时,指针值将变为无效。它不是允许随机算术的通配符类别。 [expr.add] 仍然会阻止你。
    • @abhiarora 如果我没记错的话。 “当它表示的存储达到其存储持续时间的末尾时,指针值变得无效”。这里的语言是在谈论像悬空指针这样的情况
    • @abhiarora - 就像我告诉 Ayxan 一样,当对象到达其生命周期的尽头时,可能会出现无效的指针值。它是有效的,然后变得无效。至于注释,这意味着您获得指针的合法方式受到限制。简单地说int a; int b; *(&a + 1) = 3; - 即使&a + 1 指向b,这仍然不是获取指向b 的指针的有效方法。
    猜你喜欢
    • 2015-08-05
    • 2017-11-25
    • 2014-01-26
    • 2016-08-23
    • 2011-11-04
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多