【问题标题】:Is &*vector::end() undefined behavior?&*vector::end() 是未定义的行为吗?
【发布时间】:2012-08-01 02:16:33
【问题描述】:

我认为&*vector::end() 是未定义的行为...直到我看到some post 参考Stroustrup's code

void vector_pointer_test(element_t* first, element_t* last, int number_of_times) 
{ 
       vector<element_t> container(first, last); 
       // &*container.begin() gets us a pointer to the first element 
       sort(&*container.begin(), &*container.end()); 
       unique(&*container.begin(), &*container.end()); 
}

取消引用 end() 迭代器未定义行为,还是有效?

【问题讨论】:

  • 如果Stroustrup做到了,怎么会出错?
  • @MarkRansom:这就是促使我问的原因,因为我真的认为这是(是?)错了......
  • 我也这么认为,但我倾向于置身于语言律师辩论之外。看到答案会很有趣。我一直认为end() 迭代器是不可取消引用的。
  • 在我看来完全错误。假设容器不是空的,那么&amp;*container.begin() + container.size() 是正确的做法。
  • @Brangdon:jahhaj 不是也写得很清楚吗,“假设容器不是空的”

标签: c++ iterator


【解决方案1】:

不一定是未定义的行为,但取决于迭代器的具体实现:

C++03 24.1/5 迭代器要求

就像一个指向数组的常规指针保证有一个 指针值指向数组的最后一个元素,所以对于任何 迭代器类型有一个迭代器值指向最后一个 对应容器的元素。这些值称为 过去的价值。表达式的迭代器 i 的值 *i 被定义称为可取消引用。该库从不假定过去的值是可取消引用的。

如果container.end() 不可取消引用,则相关代码的行为未定义。很多时候,向量的迭代器只是一个指针——在这些情况下,没有未定义的行为。

【讨论】:

  • 当然,指针是存在的,但是exists指针值的存在与你是否可以取消引用它无关,对吧?特别是因为您的引用似乎暗示它应该被视为一般可取消引用。
  • 所以container.end() 允许被取消引用但不保证。有趣的。按理说vector 迭代器会有这个属性,因为它们是最直接的实现。
  • @MarkRansom:我不认为他在这里依赖特定于实现的行为。如果向量在页面边界处结束怎么办?然后内存的下一页可能有一些与当前页不同的保护,这与向量实现无关(除非它竭尽全力纠正这一点,这是不太可能的)。另外,值得注意的是,迭代器在这里可能不是指针,否则这个测试用例将是多余的。
  • 一个向量的结束指针在一般情况下仍然是不可分离的。我敢打赌,没有任何规范的 stdlib 实现允许取消引用任何 end() 迭代器。
  • 另外,如果向量是空的怎么办?! (虽然我认为这可能在这里被认为是错误的。)
【解决方案2】:

这是未定义的行为。也就是说,C++ 标准未定义的行为。它可以由实现来定义。更有可能的是,它在某些情况下会碰巧起作用,而在其他情况下则不会。

在这种情况下,如果迭代器是原始指针,编译器可能会将 &*i 优化为无操作,因此它可能会起作用。 Stroustrup 可能知道他的向量使用原始指针作为迭代器。

即使编译器没有优化它,实际上,只有当向量的内存恰好被分配到段边界处时,它才有可能失败。 (或者,如果编写迭代器实现以检查不可取消引用,例如出于调试目的。)

在 C++11 中,这应该写成:

sort(container.data(), container.data()+container.size()); 

【讨论】:

  • 我觉得它不可能是一个指针,因为那会使测试用例变得毫无意义......他已经有一个迭代器的测试用例,并且如果它们是指针,那么在单独的测试用例中就没有意义(没有双关语)。所以我猜他的代码是UB?
  • 是的,这是未定义的行为。即使他的本地向量不使用迭代器的指针,符合标准的实现也可以,并且标准不需要指针无法提供的任何东西。
猜你喜欢
  • 2023-02-07
  • 2020-06-15
  • 2011-05-19
  • 1970-01-01
  • 2011-08-23
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多