std::vector<int> foo(10); int *ptr_begin = &foo[0];
到目前为止一切顺利,这保证在当前标准(23.3.6.1)中有效:
The elements of a vector are stored contiguously,meaning that if v is a vector where T is some type other than bool,then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
因此,我们可以使用指针访问向量的所有元素,因为它们存储在连续的内存块中.但那个过去的最后一个元素呢?我的意思是,执行此操作是合法的吗?
int *ptr_end = ptr_begin + foo.size()
(注意,我不是试图访问过去的最后一个值,只是为了定义一个指向它的指针 – 如果你愿意的话,相当于foo.end()).该标准仅提到通过指针算术访问元素,但显然我们不访问任何元素.
(作为旁注,过去最后一些东西的存在的定义似乎与数组的基本概念紧密相关(参见例如5.7 / 5),但在整个标准中,它似乎是连续存储的概念和数组可以互换使用.我读错了吗?)
解决方法
If both the pointer operand and the result point to elements of the
same array object,or one past the last element of the array object,
the evaluation shall not produce an overflow; otherwise,the behavior
is undefined.
第5.9节中列出了关系运算符的类似规定:
If two pointers point to elements of the same array or one beyond the
end of the array,the pointer to the object with the higher subscript
compares higher.
至于vector的缓冲区是否计算为上述目的的数组,§8.3.4规定:
An object of array type contains a contiguously allocated non-empty
set of N subobjects of type T.
这与§23.3.6.1对矢量的说法是一致的:
The elements of a vector are stored contiguously
由于指针是迭代器,因此使用标准库算法和任意内存块作为输入时,这种方法是一种方便的技巧.例如,假设您要使用lower_bound算法,但您的数据存储在MFC CArray中:
CArray<int> someInts; // populate and check for empty int* begin = someInts.GetData(); int* end = begin + someInts.GetSize(); // for bounds-checking only; don't dereference int* answer = std::lower_bound(begin,end,100);
*还有其他一些合法的操作;例如既然你知道你的向量不是空的,你可以减去一个得到指向最后一个元素的指针.重要的是不要取消引用.