O comportamento indefinido realmente ajuda os compiladores modernos a otimizar o código gerado?

Os compiladores modernos não são inteligentes o suficiente para gerar um código rápido e seguro ao mesmo tempo?

Veja o código abaixo:

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

É óbvio que o erro fora de alcance nunca acontecerá aqui, e um compilador inteligente pode gerar o próximo código:

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

Agora vamos verificar este código:

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

Pode ser alterado para esse equivalente:

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"); }
...

Além disso, sabemos que oint O tipo não tem efeitos colaterais em seu destruidor e operador de atribuição. Então, podemos traduzir o código para o próximo equivalente:

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; }
...

(Não tenho certeza de que essa otimização seja permitida pelo padrão C ++, porque exclui as etapas de alocação / desalocação de memória, mas vamos pensar na linguagem semelhante a C ++ que permite essa otimização.)

E, ok, essa otimização não é tão rápida quanto o próximo código:

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

porque há uma verificação adicionalif (50 > __tmp) que você realmente não precisa se tiver certeza de queunknown_function nunca retorna um valor menor que 50. Mas a melhoria de desempenho não é muito alta nesse caso.

Observe que minha pergunta é um pouco diferente do que esta:Comportamento indefinido vale a pena? Essa pergunta é: as vantagens das melhorias de desempenho superam as deficiências de comportamento indefinido. Ele pressupõe que um comportamento indefinido realmente ajude a otimizar um código. Minha pergunta é: é possível obter quase o mesmo nível (talvez um pouco menos) de otimização em um idioma sem comportamento indefinido como em um idioma com comportamento indefinido.

O único caso em que posso pensar em que comportamentos indefinidos podem realmente ajudar a melhorar significativamente o desempenho é o gerenciamento manual de memória. Você nunca sabe se o endereço apontado por um ponteiro não é liberado. Alguém pode ter uma cópia do ponteiro do que chamarfree nele. Seu ponteiro ainda aponta para o mesmo endereço. Para evitar esse comportamento indefinido, você precisa usar um coletor de lixo (que possui suas próprias desvantagens) ou manter uma lista de todos os ponteiros que apontam para o endereço e, quando o endereço é liberado, você precisa anular todos esses ponteiros (e verifique-osnull antes de acessá-los).

Fornecer um comportamento definido para o ambiente multiencadeado provavelmente também pode causar custos de desempenho.

PS Não tenho certeza de que um comportamento definido possa ser alcançado emCidioma, mas também o adicionei às tags.

questionAnswers(4)

yourAnswerToTheQuestion