Aren't modern compilers smart enough to be able to generate a code that is fast and safe at the same time?
Look at the code below:
std::vector<int> a(100);
for (int i = 0; i < 50; i++)
{ a.at(i) = i; }
...
It's obvious that the out of range error will never happen here, and a smart compiler can generate the next code:
std::vector<int> a(100);
for (int i = 0; i < 50; i++)
{ a[i] = i; } // operator[] doesn't check for out of range
...
Now let's check this code:
std::vector<int> a(unknown_function());
for (int i = 0; i < 50; i++)
{ a.at(i) = i; }
...
It can be changed to such equivalent:
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"); }
...
Also, we know that the int
type doesn't have side effects in its destructor and assignment operator. So we can translate the code to the next equivalent:
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; }
...
(I'm not sure that such optimization is allowed by C++ standard, because it excludes memory allocation/deallocation steps, but let's think of C++-like language that allows this optimization.)
And, OK, this optimization is not as fast as the next code:
std::vector<int> a(unknown_function());
for (int i = 0; i < 50; i++)
{ a[i] = i; }
because there is an additional check if (50 > __tmp)
which you really don't need if you are certainly sure that unknown_function
never returns a value that is less than 50. But the performance improvement is not very high in this case.
Please note that my question is little different than this question: Is undefined behavior worth it? That question is: do advantages of performance improvements outweigh shortcomings of undefined behavior. It assumes that undefined behavior really helps to optimize a code. My question is: is it possible to achieve almost the same (maybe little less) level of optimization in a language without undefined behavior as in a language with undefined behavior.
The only case I can think of where undefined behavior can really help improve performance significantly is manual memory management. You never know if the address a pointer points to is not freed. Someone can have a copy of the pointer than call free
on it. Your pointer still point to the same address. To avoid this undefined behavior you either have to use a garbage collector (which has its own disadvantages) or have to maintain a list of all pointers that point to the address, and when the address is freed you have to nullify all those pointers (and check them for null
before accessing them).
Providing defined behavior for multi-threaded environment may probably cause performance costs too.
PS I am not sure that a defined behavior may be achieved in C-like language, but added it to the tags too.