【问题标题】:Is taking the address of std::vector::operator[](size) Undefined Behavior in C++11 [duplicate]正在获取 C++11 中的 std::vector::operator[](size) 未定义行为的地址 [重复]
【发布时间】:2014-11-21 20:07:00
【问题描述】:

这是未定义的行为吗?

ptrdiff_t one() {
   std::vector<int> test(1);
   return &test[1] - &test[0];
}

这是未定义的行为吗?

ptrdiff_t zero() {
   std::vector<int> test;
   int * end = &test[0];
   int * begin = &test[0];
   return end - begin;
}

如果其中任何一个是未定义的行为,谁能帮我找到 C++11 规范中描述向量的下标运算符必须在小于(而不是小于或等于)的值上调用的部分to) 大小,反之亦然?

谢谢

【问题讨论】:

  • 我发现对于 valarray “6 如果使用值不小于数组长度的 size_t 参数调用下标运算符,则行为未定义。”在 26.6.2.4 中——我很好奇为什么矢量不存在这种清晰度。我确实搜索了一段时间,发现了很多相关的问题,但不是关于这个特殊的细微差别:我认为如果它不是未定义的行为,那么它对于 C++11 来说是新的。
  • @sehe: std::vector != C 样式数组。
  • @Xeo 我知道这一点。我会删除它 - 但不知何故,我的浏览器上没有显示该评论。 (我可能退了)
  • @hellcatv: valarray 没有用 containers 定义,其定义的表述更加模糊。
  • 我认为您的问题的解决方案是&amp;vec.data()[0]&amp;vec.data()[1] -- 或者只是vec.data()vec.data()+1 更好。禁止取消引用迭代器的规则不适用于指针,通常如果您想访问指向向量中数据的“原始指针”,请使用data()。这甚至可以处理空向量情况。

标签: c++ c++11


【解决方案1】:

是的,这些程序片段具有未定义的行为。

表101将test[0]定义为*(test.begin() + 0),如果没有元素则无效:

[C++11: 24.2.1/5]: 就像指向数组的常规指针保证有一个指针值指向数组的最后一个元素一样,所以对于任何迭代器类型,都有一个迭代器值指向对应序列的最后一个元素.这些值称为过去的值。定义了表达式*i 的迭代器i 的值称为可解引用库从不假定过去的值是可取消引用的。 [..]

在给定任何迭代器 i 的情况下,表 106 将可解引用性作为 *i 有效性的先决条件。

之后尝试获取地址并不重要:你已经破坏了你的程序。例如,您的标准库实现可能会合规地触发来自 operator* 的任何过去迭代器的断言。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 2015-06-13
    • 2023-02-07
    • 1970-01-01
    • 2013-04-16
    • 2011-12-30
    • 2013-10-12
    相关资源
    最近更新 更多