sobrecarga programacion poo operadores c++ vector indexoutofboundsexception

c++ - poo - manual de programacion android pdf



¿Por qué C++ no detecta cuándo se accede a los elementos del vector fuera de rango con los operadores[] por defecto? (2)

Entiendo que las matrices son una clase primitiva y, por lo tanto, no tienen métodos integrados para detectar errores fuera de rango. Sin embargo, la clase vectorial tiene la función incorporada .at () que detecta estos errores. Al usar espacios de nombres, cualquiera puede sobrecargar los símbolos [] para actuar como la función .at () lanzando un error cuando se accede a un valor fuera del rango del vector. Mi pregunta es esta: ¿por qué esta funcionalidad no es la predeterminada en C ++?

EDITAR: A continuación se muestra un ejemplo en pseudocódigo (creo, corríjanme si es necesario) sobrecargar el vector operador []:

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

Creo que esta función se puede escribir en un espacio de nombre definido por el usuario y es razonablemente fácil de implementar. Si esto es cierto, ¿por qué no es el predeterminado?


C ++ tiene un principio de pago único por lo que usa. Por lo tanto, las operaciones sin marcar definitivamente tienen su lugar; solo porque eres demasiado flojo para tener cuidado con tus límites no significa que deba pagar una penalización de rendimiento.

Históricamente array [] ha sido desmarcado tanto en C como en C ++. El hecho de que los idiomas de 10 a 20 años más jóvenes hicieran que una operación verificada no significara que C ++ necesitara hacer un cambio tan fundamental incompatible con versiones anteriores.


Para algo que normalmente es tan barato como [] , la comprobación de límites agrega una sobrecarga significativa.

Considerar

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

esta función se traduce en solo tres líneas de ensamblaje :

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

Ahora considere la versión de comprobación de límites usando at() :

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

Esto se convierte

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

Incluso en la ruta del código normal (sin tirar), son 8 líneas de ensamblaje, casi tres veces más.