2010-01-26 17 views
55

Stavo guardando alcuni esempi di codice C++ per un'interfaccia hardware sto lavorando con e ho notato un sacco di dichiarazioni secondo le seguenti linee:Qual è il ragionamento alla base del fatto di inserire le costanti nelle istruzioni if?

if (NULL == pMsg) return rv; 

Sono sicuro che ho sentito dire che mettere il costante prima è una buona idea, ma perché è così? È così che se hai una dichiarazione importante puoi vedere rapidamente a cosa stai confrontando o c'è dell'altro?

+4

+1 per davvero un buon titolo di domanda . – OregonGhost

+1

sono sicuro di aver visto questa domanda più di una volta, ma non riesco a trovarla ora. –

+1

@ Idan: sono rimasto sorpreso di non averlo trovato, ma dopo 5 minuti di ricerca ho rinunciato ;-) –

risposta

76

In modo da non mischiare il confronto (==) con l'assegnazione (=).

Come sapete, non è possibile assegnare a una costante. Se ci provi, il complatore ti darà un errore.

Fondamentalmente, è una delle tecniche di programmazione difensive. Per proteggersi da te stesso.

+2

Brillante - grazie mille :-) –

7

Quando la costante è la prima, il compilatore ti avviserà se scrivi accidentalmente = anziché == poiché è illegale assegnare un valore a una costante.

29

che impedisca di scrittura:

if (pMsg = NULL) return rv; 

per errore. Tuttavia, un buon compilatore ti avviserà di questo, quindi la maggior parte delle persone non usa il modo "costante prima", poiché trova difficile leggere.

+0

+1 dopo la modifica ninja. –

+8

+1 per aver menzionato che i compilatori moderni lo avvertono comunque. Un altro motivo per non farlo in C++ è evitare le insidie ​​con sovraccarico dell'operatore scritto male. ('_bstr_t', oh, quanto ti odio.) – jamesdlin

+0

+1 per aver menzionato i problemi di leggibilità/manutenzione. – Ben

8

Arresta il bug single = assignment.

Ad esempio,

if (NULL = pMsg) return rv; 

non si compila, dove come

if (pMsg = NULL) return rv; 

compilerà e darà mal di testa

2

Hanno detto, "per evitare la miscelazione di assegnazione e di confronto".

In realtà penso che sia una sciocchezza: se siete modo disciplinato che non si dimentica di mettere costante sul lato sinistro, si sicuramente non mischiare '=' con '==' , vorresti? ;)

+0

No, ma si ha più possibilità di evitare l'errore con qualcosa che richiede più sequenze di tasti di quelle che potrebbero essere causate dal non digitare abbastanza forte da ottenere il secondo =. Quindi, sai, errore di battitura. –

+0

Sono curioso di sapere quanto spesso hai fatto errori di battitura? Scommetto che non l'hai fatto. –

+6

Mi piacerebbe pensare di essere abbastanza disciplinato, ma qualunque sia lo stile di codifica, ognuno fa l'errore di battitura occasionale e questa semplice abitudine evita errori come quello di passare all'esecuzione. Un bug catturato durante la compilazione vale 10 al momento dell'esecuzione :-) –

2

I compilatori che emettono avvisi sono buoni, ma alcuni di noi nel mondo reale non possono permettersi di trattare gli avvertimenti come errori. Invertire l'ordine di variabile e costante significa che questo semplice slittamento appare sempre come un errore e impedisce la compilazione. Ci si abitua molto velocemente a questo schema e l'insetto contro cui è protetto è sottile, che è spesso difficile da trovare una volta introdotto.

8

Per chiarire cosa ho scritto in alcuni commenti, ecco un motivo non per farlo in codice C++.

Qualcuno scrive, ad esempio, una classe string e decide di aggiungere un operatore di cast per const char*:

class BadString 
{ 
public: 
    BadString(const char* s) : mStr(s) { } 

    operator const char*() const { return mStr.c_str(); } 

    bool operator==(const BadString& s) { return mStr == s.mStr; } 

    // Other stuff... 

private: 
    std::string mStr; 
}; 

Ora qualcuno si applica ciecamente il modello constant == variable programmazione "difensivo":

BadString s("foo"); 

if ("foo" == s) // Oops. This compares pointers and is never true. 
{ 
    // ... 
} 

Questo è , IMO, un problema più insidioso dell'assegnazione accidentale perché non si può dire dal sito di chiamata che qualcosa è ovviamente sbagliato.

Naturalmente, le vere lezioni sono:

  1. Non scrivere le proprie classi di stringa.
  2. Evita gli operatori di cast impliciti, specialmente quando si esegue (1).

Ma a volte hai a che fare con API di terze parti che non puoi controllare. Ad esempio, il comune della classe di stringa _bstr_t nella programmazione COM di Windows soffre di questo difetto.

+0

Ho visto molti luoghi che vietano l'overloading dell'operatore in generale. Yay C++. –

+0

Non sarebbe s == "foo" avere lo stesso problema? –

+0

@Jon Cage: No. Unintuitively, mentre '" foo "== s' non attiva l'errore di ambiguità desiderato,' s == "foo" 'fa. (L'autore potrebbe quindi implementare 'bool MyString :: operator == (const char *) const' che risolverà l'ambiguità' s == "foo", ma non farà nulla per risolvere '" foo "== s'.) – jamesdlin

0

ho dimenticato l'articolo, ma la citazione è andato qualcosa come: "Evidentemente è più facile ricordarsi di mettere la prima costante, che si sta ricordando di usare ==";))

Problemi correlati