默认情况下,为什么 C++ 不检测何时使用 [ ] 运算符访问超出范围的向量元素?

Why doesn't C++ detect when out of range vector elements are accessed with the [ ] operators by default?

我知道数组是原始数组 class,因此没有内置方法来检测超出范围的错误。然而,向量 class 有内置函数 .at() 可以检测到这些错误。通过使用名称空间,任何人都可以重载 [ ] 符号以充当 .at() 函数,方法是在访问向量范围之外的值时抛出错误。我的问题是:为什么这个功能在 C++ 中不是默认的?

编辑:下面是重载向量运算符 [ ]:

的伪代码示例(我相信 - 如果需要请纠正我)
Item_Type& operator[](size_t index) { // Verify that the index is legal.
if (index < 0 || index >= num_items) {
   throw std::out_of_range
     ("index to operator[] is out of range");
}
 return the_data[index]
}

我相信这个函数可以写入用户定义的命名空间并且相当容易实现。如果这是真的,为什么它不是默认值?

C++ 有一个只为使用付费的原则。因此,未经检查的操作肯定有一席之地;仅仅因为你懒得注意你的边界并不意味着我应该付出性能损失。

历史上数组 [] 在 C 和 C++ 中都未被选中。仅仅因为年轻 10-20 岁的语言进行了检查操作并不意味着 C++ 需要进行这种基本的向后不兼容的更改。

对于通常与 [] 一样便宜的东西,边界检查会增加大量开销。

考虑

int f1(const std::vector<int> & v, std:size_t s) { return v[s]; }

这个函数转换为just three lines of assembly:

    movq    (%rdi), %rax
    movl    (%rax,%rsi,4), %eax
    ret

现在考虑使用 at() 的边界检查版本:

int f2(const std::vector<int> & v, std:size_t s) { return v.at(s); }

这变成了

    movq    (%rdi), %rax
    movq    8(%rdi), %rdx
    subq    %rax, %rdx
    sarq    , %rdx
    cmpq    %rdx, %rsi
    jae .L6
    movl    (%rax,%rsi,4), %eax
    ret
.L6:
    pushq   %rax
    movl    $.LC1, %edi
    xorl    %eax, %eax
    call    std::__throw_out_of_range_fmt(char const*, ...)

即使在正常(非抛出)代码路径中,也有 8 行汇编 - 几乎是原来的三倍。