Ich versuche eine Protokollierung zu implementieren, die keinen Overhead erzeugt, wenn sie nicht benötigt wird (d. h. es sollte überhaupt kein Methodenaufruf durchgeführt werden). Ich möchte keinen Overhead, weil es Code mit niedriger Latenz ist. Ich habe gerade #define ENABLE_LOGS
zu meiner Header-Klasse hinzugefügt und jetzt sieht es so aus (du kannst Details ignorieren)
Jedes Mal, wenn ich eine Methode verwenden muss, sollte ich es so umgeben:
%Vor% Es ist Fehler-phrone (ich kann vergessen zu umgeben) und macht den Code schmutzig. Kann ich meinen Code irgendwie reparieren, um #ifdef
nicht jedes Mal zu verwenden?
In C # mag ich bedingt ich denke, ich brauche so etwas für C ++.
Zunächst würde es Sinn machen, nachzusehen, was da draußen schon los ist. Dies ist ein häufiges Problem und viele Leute werden es schon früher gelöst haben. Siehe z. B. stackoverflow question C ++ - Protokollierungs-Framework-Vorschläge und Dr Dobbs Ein hoch konfigurierbares Protokollierungs-Framework in C ++ .
Wenn Sie Ihre eigenen rollen, sollten Sie einige gute Ideen davon bekommen, dies getan zu haben. Es gibt verschiedene Ansätze, die ich in der Vergangenheit angewendet habe. Eine besteht darin, die Anweisung selbst bedingt zu definieren
%Vor%Ein anderer Ansatz besteht darin, die Protokollierungsklasse selbst bedingt zu definieren. Die nicht protokollierende Version enthält alles als leere Anweisungen, und Sie sind darauf angewiesen, dass der Compiler alles optimiert.
%Vor% Sie könnten Ihre Logger
-Implementierung für ENABLE_LOGS
in eine cpp-Datei unter Kontrolle des Makros setzen. Ein Problem bei diesem Ansatz besteht darin, dass Sie sicher sein sollten, die Schnittstelle so zu definieren, dass der Compiler alles optimieren kann. Verwenden Sie beispielsweise einen C-String-Parametertyp ( const char*
). In jedem Fall ist const std::string&
besser als std::string
(letzteres stellt sicher, dass es bei jedem Anruf eine Zeichenkette gibt).
Wenn Sie sich für den ersten Ansatz entscheiden, sollten Sie schließlich alles in do() { ... } while(0)
kapseln, um sicherzustellen, dass Sie kein bizarres Verhalten bekommen, wenn Sie Ihr Makro verwenden, wo eine zusammengesetzte Anweisung erwartet werden könnte.
Was ich oft sehe, ist die Verwendung der # define, um die Log-Aufrufe zu definieren, zB:
%Vor%Aber Sie möchten die Definitionen in einen Block einfügen, der Ihre Protokollierung aktiviert oder deaktiviert:
%Vor%Sie können LOG_DEBUG überall in Ihrem Code aufrufen. Wenn die Protokollierung deaktiviert ist, endet der Aufruf von LOG_DEBUG als leere Zeile in Ihrem endgültigen Code.
Ein schöner alter Trick ist:
%Vor%Dann der Code:
%Vor%wird erweitert zu:
%Vor%das macht das Protokoll. Oder:
%Vor%das macht absolut nichts. Es evaluiert nicht einmal die Funktionsargumente !!!
Der Trick ist, dass die erste Version das Komma als Argumenttrennzeichen in einem Funktionsaufruf verwendet. In der zweiten Version ist es jedoch ein unbewerteter Komma-Operator.
Einige Compiler geben jedoch falsche Warnungen über nicht erreichbaren Code.
Sie könnten #ifdef
in den Rumpf der einzelnen Funktionen einfügen. Dies vermeidet das Codeduplikationsproblem in TooTones Antwort.
Beispiel:
%Vor% Wenn ENABLE_LOGS
nicht definiert ist, macht diese Funktion nichts. Was ich vorschlagen würde ist, dass Sie eine const char*
anstelle von std::string
an diese Methode übergeben. Wenn also ENABLE_LOGS
nicht definiert ist, müssen Sie sich nicht darauf verlassen, dass der Compiler keine redundanten std::string
-Objekte erstellt.
Tags und Links c++