为什么 &x[0]+x.size() 而不是 &x[x.size()]?

Why &x[0]+x.size() instead of &x[x.size()]?

我正在阅读 C++ 之旅(第 2 版),并且遇到了这段代码(6.2 参数化类型):

template<typename T>
T* end(Vector<T>& x)
{
     return x.size() ? &x[0]+x.size() : nullptr;     // pointer to one-past-last element 
}

我不明白为什么我们使用 &x[0]+x.size() 而不是 &x[x.size()]。这是否意味着我们获取 x 中的第一个元素的地址并仅添加到该数字 x.size() 字节?

&x[x.size()] 会导致(试图)获取 x[x.size()] 的地址。但是 x[x.size()] 尝试访问越界元素;根据特定 TVector<T>::operator[] 的 API,可能会发生一些不好的事情:

|    Vector<T>::operator[] semantics      |
| ======================================= |
| return\ contr |             |           |
| type   \ -act |  unchecked  |  checked  |
| --------------------------------------- |
| reference     |    UB (1)   |    FH     |
| value         |    UB (2)   |    FH     |
| --------------------------------------- |

  • UB (1):创建对 out-of-range-element.
  • 的引用时的未定义行为
  • UB (2):尝试读取 out-of-range 元素的值时出现未定义的行为。
  • FH:来自 API 的某些错误处理操作(如果已检查)(例如抛出异常、终止...)。

对于 std::vector,例如,您将 运行 放入 UB (1),因为它的 operator[] 未选中并且 returns 是引用类型。

虽然您可以执行指针算法来计算指向缓冲区的 one-past-last(语义上 end())的指针,但您不能取消引用 one-past-last 指针。