【发布时间】:2014-01-01 10:04:13
【问题描述】:
今天我写了一些看起来像这样的东西:
void foo(std::vector<char>&v){
v.push_back('a');
char*front=&v.front();
char*back=&v.back();
size_t n1=back-front+1;
v.push_back('b');//This could reallocate the vector elements
size_t n2=back-front+1;//Is this line valid or Undefined Behavior ?
}
如果在我推回 'b' 时发生重新分配,我还能计算我的两个指针的差吗?
看了几遍标准的相关段落,我仍然无法在这一点上下定决心。
C++11 5.7.6: 当两个指向同一个数组对象的元素的指针相减时,结果是 两个数组元素的下标。结果的类型是实现定义的有符号整数 类型;此类型应与标头 (18.2) 中定义为 std::ptrdiff_t 的类型相同。作为 对于任何其他算术溢出,如果结果不适合提供的空间,则行为未定义。 换句话说,如果表达式 P 和 Q 分别指向数组对象的第 i 个和第 j 个元素, 表达式 (P)-(Q) 具有值 i - j,前提是该值适合 std::ptrdiff_t 类型的对象。 此外,如果表达式 P 指向数组对象的一个元素,或者指向数组对象的最后一个元素之后的一个元素 一个数组对象,表达式 Q 指向同一个数组对象的最后一个元素,表达式 ((Q)+1)-(P) 与 ((Q)-(P))+1 和 -((P)-((Q)+1)) 具有相同的值,如果这 表达式 P 指向数组对象的最后一个元素,即使表达式 (Q)+1 没有 指向数组对象的一个元素。 除非两个指针都指向同一个数组对象的元素,或者 超过数组对象的最后一个元素,行为未定义。
我当然知道它有效,我只是想知道它是否合法。
【问题讨论】:
-
被删除的对象不是不再是对象了吗?
-
由于
front和back可能在push_back之后悬空,这意味着没有数组,如果没有数组,则两者无法指向它。这可能会调用 UB。 -
没有人注意到应该是
back-front,而不是front-back? -
@Henrik 我更正了代码
-
@jbruni 这是一个实现细节。这个问题与标准有关。
标签: c++ c++11 language-lawyer undefined-behavior pointer-arithmetic