Domanda

In C ++ puoi inizializzare una variabile in un'istruzione if, in questo modo:

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

Perché uno dovrebbe considerare questo stile cattivo o buono? Quali sono i vantaggi e gli svantaggi?

Personalmente mi piace questo stile perché limita l'ambito della variabile pThing, quindi non può mai essere usato accidentalmente quando è NULL. Tuttavia, non mi piace che non puoi farlo:

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

Se c'è un modo per far funzionare quanto sopra, si prega di pubblicare. Ma se ciò non fosse possibile, vorrei comunque sapere il perché.

Domanda presa in prestito da qui, argomento simile ma PHP.

È stato utile?

Soluzione

L'importante è che una dichiarazione in C ++ non sia un'espressione.

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

Non puoi fare sia una dichiarazione che una logica booleana in un'istruzione if, le specifiche del linguaggio C ++ consentono espressamente un'espressione o una dichiarazione.

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

Come possiamo sapere se un è definito tra un termine e l'altro in un'espressione?

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

Morde il proiettile e usa un if interno. Le regole dell'ambito sono utili e la tua logica è esplicita:

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

Altri suggerimenti

Informazioni sui vantaggi:

Si consiglia sempre di definire le variabili quando ne hai bisogno per la prima volta, non una riga prima. Questo per migliorare la leggibilità del tuo codice, dal momento che si può dire cosa è CThing senza scorrere e cercare dove è stato definito.

Riducendo anche l'ambito di un ciclo / blocco if, la variabile non viene più referenziata dopo l'esecuzione del blocco di codice, rendendola candidata per Garbage Collection (se il linguaggio supporta questa funzione).

if (CThing* pThing = GetThing())

È cattivo stile , perché all'interno del se non si fornisce un'espressione booleana. Stai fornendo un CThing * .

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

Questo è un buon stile.

Un motivo per cui normalmente non lo faccio è a causa del bug comune di un '=' mancato in un test condizionale. Uso lint con l'errore / avvertenze impostato per catturarli. Quindi urlerà per tutti gli incarichi all'interno dei condizionali.

Solo una FYI alcuni dei vecchi complier Microsoft C ++ (Visual Studios 6 e .NET 2003 credo) non seguono abbastanza la regola di scoping in alcuni casi.

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

cout << i << endl;

Dovrei essere fuori dall'ambito, ma quello era / è un codice valido. Credo che sia stato interpretato come una funzionalità, ma secondo me è solo una non conformità. Non aderire agli standard è male. Proprio come uno sviluppatore web su IE e Firefox.

Qualcuno con VS può verificare e vedere se è ancora valido?

Questo dovrebbe essere non funziona in C ++ da anche se supporta valutazione del corto circuito . Forse Non provare quanto segue:

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

err .. vedi Risposta di Wesley Tarle

Puoi anche racchiudere il compito in un set aggiuntivo di () per impedire il messaggio di avviso.

Lo vedo come un po 'pericoloso. Il codice seguente è molto più sicuro e le parentesi graffe limitano comunque l'ambito di pThing nel modo desiderato.

Suppongo che GetThing () a volte restituisca NULL, motivo per cui ho inserito quella clausola divertente nell'istruzione if (). Impedisce che IsReallySomething () venga chiamato su un puntatore NULL.

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

nota anche che se stai scrivendo codice C ++ vuoi dare l'avvertimento del compilatore su " = " in una dichiarazione condizionale (che non fa parte di una dichiarazione) un errore.

È accettabile e buona pratica di codifica. Tuttavia, le persone che non provengono da un background di programmazione di basso livello probabilmente non sarebbero d'accordo.

Tante cose. Prima di tutto, puntatori nudi. Per favore, evitali con tutti i mezzi. Usa riferimenti, facoltativo, unique_ptr, shared_ptr. Come ultima risorsa, scrivi la tua classe che si occupa della proprietà del puntatore e nient'altro.

Usa l'inizializzazione uniforme se puoi richiedere C ++ 11 (preferibilmente C ++ 14 per evitare difetti C ++ 11): - evita confusione = vs == ed è più rigoroso nel controllare gli argomenti se ce ne sono.

if (CThing thing {})
{
}

Assicurati di implementare operator bool per ottenere una conversione prevedibile da CThing a bool. Tuttavia, tieni presente che altre persone che leggono il codice non vedrebbero subito operatore bool . Le chiamate esplicite al metodo sono generalmente più leggibili e rassicuranti. Se è possibile richiedere C ++ 17, utilizzare la sintassi dell'inizializzatore.

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

Se C ++ 17 non è un'opzione, utilizzare una dichiarazione sopra se come altri hanno suggerito.

{
  CThing thing {};
  if (thing.is_good())
  {
  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top