Storia della questione:
Le macro provengono dal linguaggio C come un modo potente per automatizzare sezioni ripetute di codice durante la fase di preprocessing. In C++, il loro utilizzo ha portato flessibilità, ma ha anche portato numerosi pericoli nascosti a causa della mancanza di controllo sui tipi e dell'inafferrabile funzionamento del preprocessore.
Problema:
I principali rischi dell'uso delle macro:
Soluzione:
Nei moderni standard C++, si raccomanda di utilizzare funzioni inline, template, constexpr, enum class, così come variabili constexpr al posto delle macro.
Esempio di codice:
// Male: #define MAX(a, b) ((a) > (b) ? (a) : (b)) // Bene: template<typename T> constexpr T max(T a, T b) { return a > b ? a : b; }
Caratteristiche chiave:
Può una macro essere più pericolosa di una funzione inline?
Sì. Una macro non è soggetta alle regole di sintassi e ai tipi. È possibile un risultato inaspettato quando si passano parametri con effetti collaterali.
#define SQUARE(x) ((x) * (x)) int y = 5; int z = SQUARE(y++); // y viene incrementato due volte!
È #include anche una macro?
No, #include è una direttiva del preprocessore, ma l'uso di macro e include è correlato: tramite una macro è possibile modificare l'elenco dei file da includere (estremamente sconsigliato).
Si può fare debug a una macro come a una funzione normale?
No, il debugger espande la macro e mostra il testo già sostituito, non ci sono entità nominate separate.
Nel vecchio codice sono state definite numerose macro di calcolo con effetti (ad esempio, incremento), il che ha portato a bug difficili da rilevare durante l'uso di nuove funzionalità.
Pro:
Contro:
Durante il refactoring, le macro sono state sostituite da funzioni template e constexpr, e enum class è stata utilizzata al posto delle macro flag.
Pro:
Contro: