Why doesn't C++ detect when out of range vecto

2019-01-27 06:53发布

问题:

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++?

EDIT: 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?

回答1:

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

Consider

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

this function translates to just three lines of assembly:

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

Now consider the bounds-checking version using at():

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

This becomes

    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*, ...)

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



回答2:

C++ has a principle of only pay for what you use. Therefore unchecked operations definitely have their place; just because you're too lazy to be careful about your bounds doesn't mean I should have to pay a performance penalty.

Historically array [] has been unchecked in both C and C++. Just because languages 10-20 years younger made that a checked operation doesn't mean C++ needs to make such a fundamental backward-incompatible change.