Я понимаю, что массивы являются примитивным классом и поэтому не имеют встроенных методов для обнаружения ошибок вне диапазона. Тем не менее, векторный класс имеет встроенную функцию .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 ++ должен сделать такое фундаментальное обратное несовместимое изменение.