Eine schönere Methode:
#ifdef _DEBUG
#define DBOUT cout // or any other ostream
#else
#define DBOUT 0 && cout
#endif
DBOUT << "This is a debug build." << endl;
DBOUT << "Some result: " << doSomething() << endl;
Solange Sie tun nichts seltsam, Funktionen aufgerufen und weitergegeben DBOUT
wird nicht aufgerufen werden in Release-Builds. Dieses Makro funktioniert aufgrund der Priorität des Operators und des logischen UND. Weil &&
eine niedrigere Priorität als <<
hat, kompilieren Sie Builds DBOUT << "a"
als 0 && (cout << "a")
. Das logische AND wertet den Ausdruck auf der rechten Seite nicht aus, wenn der linke Ausdruck null oder false
ergibt; Da der linke Ausdruck immer zu Null führt, wird der rechte Ausdruck immer von jedem anderen Compiler entfernt, der es wert ist, verwendet zu werden, außer wenn alle Optimierungen deaktiviert sind (und selbst dann kann offensichtlich nicht erreichbarer Code weiterhin ignoriert werden).
)
Hier ist ein Beispiel für seltsame Dinge, die dieses Makro brechen:
DBOUT << "This is a debug build." << endl, doSomething();
Uhr der Kommas. doSomething()
wird immer aufgerufen, unabhängig davon, ob _DEBUG
definiert ist oder nicht. Dies liegt daran, die Aussage in Release ausgewertet baut als:
(0 && (cout << "This is a debug build." << endl)), doSomething();
// evaluates further to:
false, doSomething();
Um Komma mit diesem Makro zu verwenden, muss das Komma in Klammern eingewickelt werden, etwa so:
DBOUT << "Value of b: " << (a, b) << endl;
Ein weiteres Beispiel:
(0 && (cout << "Hello, ")) << "World" << endl;
// evaluates further to:
false << "World" << endl;
:
(DBOUT << "Hello, ") << "World" << endl; // Compiler error on release build
In Release-Builds, wird dies als ausgewertet
verursacht einen Compilerfehler, da bool
nicht durch einen Zeiger char
nach links verschoben werden kann, sofern kein benutzerdefinierter Operator definiert ist. Diese Syntax verursacht auch zusätzliche Probleme:
(DBOUT << "Result: ") << doSomething() << endl;
// evaluates to:
false << doSomething() << endl;
Genau wie wenn das Komma schlecht verwendet wurde, wird doSomething()
noch genannt, weil ihr Ergebnis auf den linken Shift-Operator übergeben werden muss. (Dies kann nur auftreten, wenn ein benutzerdefinierter Operator definiert ist, dass links verschiebt ein bool
durch einen char
Zeiger;. Andernfalls ein Compiler-Fehler auftritt)
Sie DBOUT << ...
nicht klammern. Wenn Sie eine literale Ganzzahlverschiebung in Klammern setzen möchten, dann klammern Sie sie in Klammern, aber mir ist kein einziger guter Grund bekannt, einen Stream-Operator in Klammern zu setzen.
Danke! Ich fing an, selbst etwas in dieser Richtung zu denken, und ich bin froh zu sehen, dass ich nicht der Einzige bin, der es dachte. Ich werde es am Montag bei der Arbeit ausprobieren und sehen, wie gut der Compiler den Stream optimieren kann. – Emanuel
Jeder, der diese Methode verwendet, beachtet bitte den Punkt, dass einige Elemente im Freigabemodus nicht optimiert werden. Wenn Sie: '' 'debug << someCPUIntensiveFunctionOrFunctionWhichMayAffectState() <<" \ n "' '' es wird immer noch im Freigabemodus ausführen. Ich vermisste diese Cavet das erste Mal –