A expressão de encadeamento de std::string no código de Bjarne Stroustrup exibe comportamento indefinido?
Na 4ª edição de "The C Programming Language" de Bjarne Stroustrup , um trecho de código exemplifica o encadeamento usando o método de substituição de std::string:
void f2() {
std::string s = "but I have heard it works even if you don't believe in it";
s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
assert(s == "I have heard it works only if you believe in it");
}
Este código, no entanto, exibe comportamento não especificado em vez de invocar comportamento indefinido.
A razão para esse comportamento não especificado está na ordem de avaliação, que não é especificada para subexpressões de chamadas de função encadeadas. Nesse caso, as chamadas de função s.find são avaliadas antes ou depois da primeira chamada s.replace, alterando o comprimento da string resultante e afetando o resultado da chamada find subsequente.
O exemplo na pergunta demonstra isso: quando avaliados por compiladores diferentes (clang, gcc), resultados diferentes são obtidos devido a ordens de avaliação variadas.
Detalhes
Os argumentos de função têm uma ordem de avaliação não especificada e, embora o encadeamento de chamadas de função introduz uma ordem de avaliação da esquerda para a direita para cada invocação de função, os argumentos de cada chamada são sequenciados antes apenas de em relação a aquela chamada de função específica.
No exemplo, essa indeterminação surge na avaliação de s.find("even") e s.find(" don't") em relação a s.replace(0, 4, "").
Ignorando outros sub - quebras de expressão, a sequência de etapas de avaliação e sua interdependência podem ser descritas da seguinte forma:
Step 1: s.replace(0, 4, "") // A Step 2: s.find("even") // B Step 3: s.replace(B, 4, "only") // C Step 4: s.find("don't") // D Step 5: s.replace(D, 6, "") // E
Enquanto A é sequenciado antes de B, que por sua vez é sequenciado antes de C, não há nenhuma relação de sequenciamento entre B e D em relação a A. Como resultado, D pode ser avaliado antes ou depois de A, levando a resultados diferentes com base na sequência escolhida.
C 17 Mudanças
O padrão C 17 fortalece a ordem das regras de avaliação para expressões pós-fixadas e sua lista de expressões, dando ao código em questão um comportamento bem especificado. A sequência é a seguinte:
Portanto, em C 17 e posterior, esse código sempre será avaliado corretamente.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3