2013-08-13 16 views
30

So che static_assert asserisce in fase di compilazione e assert - in fase di esecuzione, ma qual è la differenza nella pratica? Per quanto ho capito, in fondo in fondo sono pezzi di codice, comeQual è la differenza tra assert e static_assert?

if (condition == false) exit(); 
  • Qualcuno può darmi un esempio di dove solostatic_assert funzionerà, o soloassert?
  • Fanno qualcosa di semplice non possono fare una dichiarazione if?
  • È una cattiva pratica usarli?
+0

'static_assert' è una dichiarazione, integrata nel linguaggio principale. Non si espande in nulla perché se non riesce, la compilazione si interrompe. – jrok

+4

@KerrekSB Ho chiesto ** tre ** domande chiare, per favore prenditi il ​​tempo di leggerle prima di fare una supposizione – Oleksiy

+1

Usa asserire per specificare che c'è un errore nella tua logica di programmazione e che dovrebbe essere corretto nel codice. un 'if' è usato per diramarsi tra diversi percorsi logici nel codice. Questa è una grande differenza – Default

risposta

35

Tu fai tre domande, quindi proverò a rispondere a ciascuna di esse.

  • Qualcuno può darmi un esempio di dove solostatic_assert funzionerà, o soloassert?

static_assert è buono per testare la logica nel codice in fase di compilazione. assert è utile per verificare un caso durante l'esecuzione che si prevede debba sempre avere un risultato, ma forse potrebbe in qualche modo produrre un risultato imprevisto in circostanze impreviste.Ad esempio, è necessario utilizzare solo assert per determinare se un puntatore passato in un metodo è null quando sembra che non dovrebbe mai verificarsi. static_assert non lo prenderebbe.

  • Fanno tutto ciò che una semplice dichiarazione if non può fare?

assert può essere utilizzato per rompere l'esecuzione del programma, così si potrebbe usare un if, un messaggio di errore, e quindi interrompere l'esecuzione del programma per ottenere un effetto simile, ma assert è un po 'più semplice per quel caso. static_assert è ovviamente valido solo per il rilevamento dei problemi di compilazione mentre uno if deve essere programmaticamente valido e non può valutare le stesse aspettative in fase di compilazione. (Un if può essere utilizzato per sputare un messaggio di errore in fase di esecuzione, tuttavia.)

  • È una cattiva pratica usarli?

Niente affatto!

+0

Una buona risposta, tuttavia, aggiungendo che assert (la variante run-time) funziona solo nelle build di debug ed è un noop in release è probabilmente una buona idea. Che può essere buono, su una dichiarazione if, con un ampio test di debug, per rimuovere qualche eventuale errore superfluo verificando l'ottimizzazione per i build di rilascio. Un avvertimento da considerare non mettere la logica di cambio di stato tra parentesi di un assert, poiché la logica risultante non esiste nelle versioni di release ... quindi con assert (x ++ <12), ad esempio, x ++ non esiste nelle build di rilascio, solo nel debug. – Kit10

1

static_assert è una direttiva del compilatore. Permette di controllare le informazioni sul tipo al momento della compilazione. Ciò causerà un errore di compilazione e produrrà un messaggio di errore che nella maggior parte degli IDE viene rilevato e visualizzato nella finestra di errore dell'IDE.

static_assert(sizeof(int) == 4,"int should be 4 bytes"); 

assert è per il runtime, è possibile controllare il valore di una variabile. Se l'asserzione fallisce, l'asserzione si innescherà. Ciò causerà un testo di messaggio di errore che apparirà in fase di esecuzione in alcuni sistemi operativi (affermare attuazione dipendente)

assert(("mypointer should never be null!", mypointer != nullptr)); 
+1

compilatore "direttiva" probabilmente non è proprio la terminologia che userei ... –

+0

La macro assert definita in '' non accetta due argomenti – Joe

+0

@joe, giusto, risolve la sintassi. –

11

static_assert è destinato a fare compilazione sicuro con il messaggio specificato, mentre tradizionale assert è destinato a terminare la esecuzione del tuo programma.

6

OK, sarò morso:

  • Solo static_assert opere se si vuole la compilazione di smettere senza successo se una condizione statica viene violata: static_assert(sizeof(void*) != 3, "Wrong machine word size"); * Solo affermazioni dinamiche può prendere condizioni dinamiche: assert(argc == 1);

  • Le dichiarazioni semplici if devono essere valide e compilabili; asserzioni statiche causano errori di compilazione.

  • No.

*) Un esempio pratico potrebbe essere quello di prevenire l'abuso di costruzioni template generici come int x; std::move<int&&>(x).

3

È una cattiva pratica usarli?

In caso di abuso, sì, in particolare assert.

Un abuso dipende dalle istruzioni assert attive. Non dovresti mai dipendere da assert per fare qualcosa perché il codice può essere compilato con NDEBUG definito e quindi assert non fa nulla. Il codice di produzione viene spesso compilato con NDEBUG definito per garantire che tali istruzioni assert scompaiano.

A meno che non si stia scrivendo un programma one-off che non durerà per più di un giorno o due, non si dovrebbe utilizzare per convalidare l'input dell'utente. Gli utenti non si preoccupano di dove il codice non è riuscito e il messaggio che viene stampato sembra una lingua straniera per molti utenti. Non dice all'utente come correggere l'errore. È anche molto spietato, dal design. Il messaggio emesso in risposta a un errore di input dell'utente dovrebbe essere un messaggio che indica all'utente come risolvere il problema. L'azione migliore dopo il messaggio è quella di offrire all'utente un modo per correggere l'errore. Se ciò non può essere fatto e se l'unica risposta valida è quella di terminare il programma, il programma dovrebbe terminare in modo pulito. In base alla progettazione, assert non determina uno spegnimento pulito. Chiama abort() anziché exit().

Una conseguenza di abort() su molte macchine è la produzione di un core dump. Un core dump è un grande messaggio di errore per un programmatore. Con un core dump, un programmatore può usare il debugger per vedere cosa è andato storto in grande dettaglio. Uno svantaggio di abort() è che le cose non vengono ripulite. Abort "termina il programma senza eseguire distruttori per oggetti di durata di memorizzazione automatica o statica e senza chiamare le funzioni passate a atexit()."

Bottom line: Va bene (e buono) utilizzare assert per verificare errori di programmazione, ma solo in un'impostazione non di produzione. Usa qualcos'altro per verificare gli errori degli utenti.

Problemi correlati