Recentemente, encontrei algo semelhante às seguintes linhas:
#include <string>
// test if the extension is either .bar or .foo
bool test_extension(const std::string& ext) {
return ext == ".bar" || ".foo";
// it obviously should be
// return ext == ".bar" || ext == ".foo";
}
Obviamente, a função não faz o que o comentário sugere. Mas esse não é o ponto aqui. Observe que esta não é uma duplicata de Você pode usar 2 ou mais condições OR em uma instrução if? desde que eu estou ciente de como você escreveria a função corretamente!
Comecei a me perguntar como um compilador poderia tratar esse trecho. Minha primeira intuição seria que isso seria compilado return true;basicamente. Ao incluir o exemplo no godbolt , mostrou que nem o GCC 9.2 nem o clang 9 fazem essa otimização com otimização -O2.
No entanto, alterar o código para 1
#include <string>
using namespace std::string_literals;
bool test_extension(const std::string& ext) {
return ext == ".bar"s || ".foo";
}
parece fazer o truque, já que a montagem agora é essencialmente:
mov eax, 1
ret
Então, minha pergunta principal é: existe algo que eu perdi que não permite que um compilador faça a mesma otimização no primeiro trecho?
1 Com ".foo"sisso nem compilaria, pois o compilador não deseja converter um std::stringpara bool;-)
Editar
O seguinte trecho de código também é otimizado "corretamente" para return true;:
#include <string>
bool test_extension(const std::string& ext) {
return ".foo" || ext == ".bar";
}
operator==(string const&, string const&)seja noexceptenquanto operator==(string const&, char const*)não é? Não tenho tempo para aprofundar isso agora.
foo || ext == ".bar", a chamada é otimizada (consulte editar). Isso contradiz sua teoria?
a || bsignifica "avaliar a expressão bapenas se a expressão afor false". É ortogonal ao tempo de execução ou tempo de compilação. true || foo()pode ser otimizado para true, mesmo que foo()tenha efeitos colaterais, porque (não importa se otimizado ou não) o lado direito nunca é avaliado. Mas foo() || truenão pode ser otimizado, a truemenos que o compilador possa provar que a chamada foo()não tem efeitos colaterais observáveis.
xor eax,eax, embora sem essa opção chame a função de comparação de cadeias. Não tenho ideia do que fazer com isso.

string::compare(const char*)tem alguns efeitos colaterais que o compilador não eliminará (queoperator==(string, string)não possui)? Parece improvável, mas o compilador já determinou que o resultado é sempre verdadeiro (também temmov eax, 1ret) mesmo para o primeiro trecho.