Хотя разработчики компиляторов C настаивают на том, что для оптимизации необходим неограниченный UB, это было бы неверно для хорошо спроектированного языка вне некоторых узких обстоятельств.

современные компиляторы не достаточно умны, чтобы создавать быстрый и безопасный код одновременно?

Посмотрите на код ниже:

std::vector<int> a(100);
for (int i = 0; i < 50; i++)
    { a.at(i) = i; }
...

Очевидно, что ошибка вне диапазона никогда не произойдет, и умный компилятор может сгенерировать следующий код:

std::vector<int> a(100);
for (int i = 0; i < 50; i++)
    { a[i] = i; } // operator[] doesn't check for out of range
...

Теперь давайте проверим этот код:

std::vector<int> a(unknown_function());
for (int i = 0; i < 50; i++)
    { a.at(i) = i; }
...

Его можно изменить на такой эквивалент:

std::vector<int> a(unknown_function());
size_t __loop_limit = std::min(a.size(), 50);
for (int i = 0; i < __loop_limit; i++)
    { a[i] = i; }
if (50 > a.size())
    { throw std::out_of_range("oor"); }
...

Кроме того, мы знаем, чтоint Тип не имеет побочных эффектов в своем деструкторе и операторе присваивания. Таким образом, мы можем перевести код в следующий эквивалент:

size_t __tmp = unknown_function();
if (50 > __tmp)
    { throw std::out_of_range("oor"); }
std::vector<int> a(__tmp);
for (int i = 0; i < 50; i++)
    { a[i] = i; }
...

(Я не уверен, что такая оптимизация допускается стандартом C ++, потому что она исключает этапы выделения / освобождения памяти, но давайте подумаем о C ++ -подобном языке, который позволяет эту оптимизацию.)

И, хорошо, эта оптимизация не такая быстрая, как следующий код:

std::vector<int> a(unknown_function());
for (int i = 0; i < 50; i++)
    { a[i] = i; }

потому что есть дополнительная проверкаif (50 > __tmp) который вам действительно не нужен, если вы уверены, чтоunknown_function никогда не возвращает значение меньше 50. Но в этом случае улучшение производительности не очень велико.

Обратите внимание, что мой вопрос немного отличается от этого вопроса:Стоит ли неопределенное поведение? Вопрос в том, перевешивают ли преимущества улучшения производительности недостатки неопределяемого поведения. Предполагается, что неопределенное поведение действительно помогает оптимизировать код. Мой вопрос: возможно ли достичь почти такого же (возможно, чуть меньшего) уровня оптимизации в языке без неопределенного поведения, как в языке с неопределенным поведением.

Единственный случай, который я могу придумать, где неопределенное поведение действительно может значительно повысить производительность, - это ручное управление памятью. Вы никогда не знаете, не освобожден ли адрес, на который указывает указатель. Кто-то может иметь копию указателя, чем звонитьfree в теме. Ваш указатель по-прежнему указывает на тот же адрес. Чтобы избежать этого неопределенного поведения, вы должны либо использовать сборщик мусора (который имеет свои недостатки), либо вести список всех указателей, которые указывают на адрес, а когда адрес освобождается, вы должны аннулировать все эти указатели (и проверить их наnull прежде чем получить к ним доступ).

Предоставление определенного поведения для многопоточной среды также может привести к снижению производительности.

PS Я не уверен, что определенное поведение может быть достигнуто вC-подобный язык, но тоже добавил его в теги.

Ответы на вопрос(4)

Ваш ответ на вопрос