Pergunta

Em C ++ você pode inicializar uma variável em uma instrução if, assim:

if (CThing* pThing = GetThing())
{
}

Por que alguém iria considerar isso ruim ou bom estilo? Quais são as vantagens e desvantagens?

Pessoalmente eu gosto deste estilo porque limita o escopo da variável pThing, por isso nunca pode ser usado acidentalmente quando é NULL. No entanto, eu não gosto que você não pode fazer isso:

if (CThing* pThing = GetThing() && pThing->IsReallySomeThing())
{
}

Se há uma maneira de fazer o trabalho acima, por favor poste. Mas se isso não é apenas possível, eu ainda gostaria de saber por quê.

Pergunta emprestado a partir daqui, tema semelhante, mas PHP.

Foi útil?

Solução

O importante é que uma declaração em C ++ não é uma expressão.

bool a = (CThing* pThing = GetThing()); // not legit!!

Você não pode fazer tanto uma declaração e lógica booleana em uma instrução if, C ++ especificação linguagem permite especificamente uma expressão ou uma declaração.

if(A *a = new A)
{
    // this is legit and a is scoped here
}

Como podemos saber se um é definida entre um termo e outro em uma expressão?

if((A *a = new A) && a->test())
{
    // was a really declared before a->test?
}

morder a bala e usar um interno se. As regras de escopo são úteis e sua lógica é explícito:

if (CThing* pThing = GetThing())
{
    if(pThing->IsReallySomeThing())
    {
    }
}

Outras dicas

Sobre as vantagens:

É sempre recomendável para definir variáveis ??quando você precisar deles, não uma linha antes. Isto é para melhorar a legibilidade do seu código, uma vez que um pode dizer o que CThing é sem rolagem e procurar onde ele foi definido.

reduzindo também espaço para um loop / if bloco, faz com que a variável a ser não referenciados após a execução do bloco de código, o que o torna um candidato para coleta de lixo (se o idioma suporte a esse recurso).

if (CThing* pThing = GetThing())

É mau estilo , porque dentro do if você não está fornecendo uma expressão booleana. Você está fornecendo um CThing*.

CThing* pThing = GetThing();
if (pThing != NULL)

Este é um bom estilo.

Uma razão que eu normalmente não fazer isso é por causa do erro comum de uma falta '=' em um teste condicional. Eu uso fiapos com o erro / avisos definido para pegar aqueles. Será, então grite sobre todas as atribuições dentro condicionais.

Apenas um FYI alguns dos compliers mais velhos Microsoft C ++ (Visual Studios 6 e .NET 2003 eu acho) não chegam a seguir a regra de escopo em alguns casos.

for(int i = 0; i > 20; i++) {
     // some code
}

cout << i << endl;

Eu deveria estar fora de alcance, mas que foi / é um código válido. Eu acredito que foi jogado fora como um recurso, mas na minha opinião é apenas incumprimento. Não aderindo aos padrões é ruim. Assim como um desenvolvedor web sobre IE e Firefox.

Pode alguém com check VS e ver se isso ainda é válido?

Este deve não funciona no C ++ desde mesmo que ele suporta curto-circuito avaliação . Talvez Não tente o seguinte:

if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing()))
{
}

err .. ver a resposta de Wesley Tarle

Você também pode englobar a atribuição de um conjunto extra de () para impedir que a mensagem de aviso.

Eu vejo isso como uma espécie de perigoso. O código abaixo é muito mais seguro e as chaves que encerram ainda vai limitar o âmbito da pThing da maneira que você quiser.

Estou assumindo GetThing () às vezes retorna NULL é por isso que eu coloquei essa cláusula engraçado na declaração if (). Ele impede IsReallySomething () sendo chamado em um ponteiro NULL.

{
    CThing *pThing = GetThing();
    if(pThing ? pThing->IsReallySomeThing() : false)
    {
    // Do whatever
    }
}

Além disso, observe que, se você está escrevendo código C ++ você quiser fazer o aviso do compilador sobre "=" em uma declaração condicional (que não faz parte de uma declaração) um erro.

É prática de codificação aceitável e bom. No entanto, as pessoas que não vêm de um baixo nível de codificação fundo provavelmente discordar.

muitas coisas. Primeiro de tudo, descobrir ponteiros. Por favor, evitá-los por todos os meios. Use referências, opcional, unique_ptr, shared_ptr. Como o último recurso, escrever sua própria classe que lida com propriedade ponteiro e nada mais.

Use a inicialização uniforme se você pode exigir C ++ 11 (C ++ 14 preferia evitar C ++ 11 defeitos): -. Evita = vs == confusão e é mais rigorosa na verificação os argumentos, se houver algum

if (CThing thing {})
{
}

Certifique-se de implementar operator bool para obter conversão previsível a partir CThing para bool. No entanto, tenha em mente que outras pessoas lendo o código não veria operator bool imediatamente. chamadas explícitas método são geralmente mais legível e reconfortante. Se você pode exigir C ++ 17, o uso initializer sintaxe.

if (CThing thing {}; thing.is_good())
{
}

Se C ++ 17 não é uma opção, use uma declaração acima, se, como já foi sugerido.

{
  CThing thing {};
  if (thing.is_good())
  {
  }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top