Às vezes, uma if
instrução pode ser um tanto complicada ou longa, portanto, por uma questão de legibilidade, é melhor extrair chamadas complicadas antes de if
.
por exemplo:
if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
// do stuff
}
nisso
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
if (b1 || b2)
{
//do stuff
}
(desde exemplo não é que ruim, é apenas para ilustração ... imaginar outras chamadas com múltiplos argumentos, etc.)
Mas com esta extração perdi a avaliação de curto-circuito (SCE).
- Eu realmente perco o SCE todas as vezes? Existe algum cenário onde o compilador pode "otimizá-lo" e ainda fornecer SCE?
- Existem maneiras de manter a legibilidade aprimorada do segundo snippet sem perder o SCE?
c++
if-statement
short-circuiting
side-effects
relaxxx
fonte
fonte
Respostas:
Uma solução natural seria assim:
Tem a vantagem de ser fácil de compreender, ser aplicável a todos os casos e ter comportamento em curto-circuito.
Esta foi minha solução inicial: um bom padrão em chamadas de método e corpos de loop for é o seguinte:
Obtém-se os mesmos benefícios de desempenho agradáveis da avaliação de curto-circuito, mas o código parece mais legível.
fonte
if
" também é um sinal de que sua função ou método é muito grande e deve ser dividido em outros menores. Nem sempre é a melhor maneira, mas muitas vezes é!b2
corretamente e você obterásomeConditionAndSomeotherConditionIsTrue
, não muito significativo. Além disso, tenho que manter um monte de variáveis em minha pilha mental durante este exercício (e tbh até parar de trabalhar neste escopo). Eu escolheria aSJuan76
solução número 2 de ou simplesmente colocaria tudo em uma função.Tenho tendência a decompor as condições em várias linhas, ou seja:
Mesmo ao lidar com vários operadores (&&), você só precisa avançar o recuo com cada par de colchetes. O SCE ainda entra em ação - não há necessidade de usar variáveis. Escrever código dessa maneira tornou-o muito mais legível para mim já há anos. Exemplo mais complexo:
fonte
Se você tiver longas cadeias de condições e o que manter em curto-circuito, poderá usar variáveis temporárias para combinar várias condições. Tomando seu exemplo, seria possível fazer, por exemplo,
Se você tiver um compilador compatível com C ++ 11, poderá usar expressões lambda para combinar expressões em funções, semelhante ao anterior:
fonte
1) Sim, você não tem mais SCE. Caso contrário, você teria que
funciona de uma forma ou de outra, dependendo se houver uma
if
declaração posterior. Muito complexo.2) Isso é baseado em opinião, mas para expressões razoavelmente complexas, você pode fazer:
Se for muito complexo, a solução óbvia é criar uma função que avalie a expressão e chamá-la.
fonte
Você também pode usar:
e o SCE funcionará.
Mas não é muito mais legível do que por exemplo:
fonte
b = b || otherComplicatedStuff();
e @SargeBorsch fez uma edição para remover o SCE. Obrigado por me avisar sobre essa mudança @Ant.Não acho que essa otimização seja permitida; especialmente
OtherComplicatedFunctionCall()
pode ter alguns efeitos colaterais.Eu prefiro refatorá-lo em uma função ou variável com um nome descritivo; que irá preservar a avaliação de curto-circuito e a legibilidade:
E conforme implementamos com
getSomeResult()
base emSomeComplicatedFunctionCall()
eOtherComplicatedFunctionCall()
, poderíamos decompor-os recursivamente se ainda forem complicados.fonte
Não, não precisa, mas é aplicado de forma diferente:
Aqui, o compilador nem mesmo rodará
OtherComplicatedFunctionCall()
seSomeComplicatedFunctionCall()
retornar verdadeiro.Aqui, ambas as funções serão executadas porque devem ser armazenadas em
b1
eb2
. Ffb1 == true
entãob2
não será avaliado (SCE). MasOtherComplicatedFunctionCall()
já foi executado.Se não
b2
for usado em nenhum outro lugar, o compilador pode ser inteligente o suficiente para embutir a chamada de função dentro do if se a função não tiver efeitos colaterais observáveis.Depende. Você precisa
OtherComplicatedFunctionCall()
executar por causa dos efeitos colaterais ou o impacto no desempenho da função é mínimo, então você deve usar a segunda abordagem para facilitar a leitura. Caso contrário, siga o SCE na primeira abordagem.fonte
Outra possibilidade de curto-circuito e ter as condições em um só lugar:
Você poderia colocar o loop em uma função e deixar a função aceitar uma lista de condições e gerar um valor booleano.
fonte
Muito estranho: você está falando sobre legibilidade quando ninguém menciona o uso de comentário dentro do código:
Além disso, sempre avanço minhas funções com alguns comentários, sobre a própria função, sobre sua entrada e saída, e às vezes coloco um exemplo, como você pode ver aqui:
Obviamente, a formatação a ser usada para seus comentários pode depender de seu ambiente de desenvolvimento (Visual studio, JavaDoc no Eclipse, ...)
No que diz respeito ao SCE, presumo que você queira dizer o seguinte:
fonte
A legibilidade é necessária se você trabalhar em uma empresa e seu código for lido por outra pessoa. Se você escreve um programa para você mesmo, depende de você se deseja sacrificar o desempenho em prol de um código compreensível.
fonte