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

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

本文关键字:元素 检测 C++ 范围 情况下 默认 访问 运算符 为什么      更新时间:2023-10-16

我知道数组是原始类,因此没有内置的方法来检测范围错误。但是,矢量类具有内置函数.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]
}

我相信此功能可以写入用户定义的名称空间中,并且很容易实现。如果这是真的,为什么不默认?

通常与[]一样便宜的东西,范围检查增加了一个重要的开销。

考虑

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

此功能仅转化为三行组装:

    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    $2, %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行组装 - 几乎是

的三倍。

c 的原则仅为您使用的东西付费。因此,不受组织的操作绝对有自己的位置;仅仅因为您懒得谨慎对待自己的界限并不意味着我应该支付绩效罚款。

历史上的数组[]在C和C 中都没有选中。仅仅是因为10-20岁的语言使检查操作并不意味着C 需要做出如此基本的向后兼容更改。