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

2021-12-21 00:00:00 indexoutofboundsexception vector c++

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

I understand that arrays are a primitive class and therefore do not have built in methods to detect out of range errors. However, the vector class has the built in function .at() which does detect these errors. By using namespaces, anyone can overload the [ ] symbols to act as the .at() function by throwing an error when a value out of the vector's range is accessed. My question is this: why is this functionality not default in C++?

下面是重载向量运算符 [ ] 的伪代码示例(我相信 - 如果需要请纠正我):

Below is an example in pseudocode (I believe - correct me if needed) of overloading the vector operator [ ]:

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]
}

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

I believe this function can be written into a user-defined namespace and is reasonably easy to implement. If this is true, why is it not default?

推荐答案

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

For something that's normally as cheap as [], bounds checking adds a significant overhead.

考虑

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

这个函数转化为只有三行汇编:

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

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

Now consider the bounds-checking version using 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 行汇编代码 - 几乎是其三倍.

Even in the normal (non-throwing) code path, that's 8 lines of assembly - almost three times as many.

相关文章