C++ Long switch-Anweisung oder suchen Sie mit Karte?
In meinem C++ - Anwendung, habe ich einige Werte, die als codes vertreten andere Werte. Übersetzen des codes, ich habe debating zwischen der Verwendung einer switch-Anweisung oder eine stl-map. Der switch würde wie folgt Aussehen:
int code;
int value;
switch(code)
{
case 1:
value = 10;
break;
case 2:
value = 15;
break;
}
Die Karte wäre ein stl::map<int, int>
und übersetzung wäre eine einfache lookup mit dem code als Schlüssel verwendet Wert.
Welches ist besser/effizienter/Reiniger/akzeptiert? Warum?
value = 5 * (code + 1);
- Ausgezeichnet. Es sei denn, Sie sind nicht die eigentlichen Werte...
- +1 für eine interessante Frage.
- Wie viele verschiedene übersetzungen benötigen Sie? Das wird eine tiefgreifende Wirkung auf die Entscheidungsfindung, die gehen auf. DH. Wenn Sie nur Fall 1 und 2 ist, sollten Sie wahrscheinlich ersetzen Sie es mit einer if-Anweisung.
- Setzen Sie die Auswahl-Logik in eine eigene Funktion, damit können Sie one-liner case 1: return 10; für jede option. Nicht zu brechen, reduziert auch das Risiko von Fehlern.
- Wenn die Ganzzahlen werden in einer Datei gespeichert, wie es bereits erwähnt wurde, in einem Kommentar, den ich schreiben würde, ein Programm zu generieren, die lookup-Tabelle aus diesen Dateien in form von .h/.c-Dateien, und kompilieren Sie es in das Projekt. Die Adressen der Wartung Problem. Wieder,, wenn der Wertebereich ist ziemlich begrenzt statische array-lookup-Tabelle ist die Schnellste Lösung. Ansonsten haben Sie, um code zu generieren, das füllt die Karte.
- fügen Sie zur Umsetzung der
default
Fall vermeiden Ausführlichkeit?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Persönlich würde ich die Karte verwenden, deren Nutzung impliziert einen Daten-lookup - mit einem Schalter ein-weist in der Regel einen Unterschied im Verhalten des Programms. Außerdem ändern sich die Daten, die die Zuordnung ist einfacher, mit einer Karte als mit einem Schalter.
Wenn die Leistung ist ein echtes Problem, profiling ist die einzige Möglichkeit, um eine brauchbare Antwort. Ein Schalter kann nicht schneller sein, wenn die Abteilung mispredictions passieren oft genug.
Einen anderen Ansatz, um darüber nachzudenken ist, ob nicht mehr Sinn machen, zu kombinieren, den code und den zugehörigen Wert in einem datastructure, vor allem, wenn die Reihe von codes und Werten ist die statische:
Wenn Ihr codes sind zusammenhängend genug, und Ihre Reichweite erlauben, Sie würde viel besser mit dem altmodischen unkompliziert array, so etwas wie
dann die switch-Anweisung umgeschrieben werden kann als einfach als
Wert = lookup[code];
alle anderen Optionen führen zusätzliche Kosten zu einem gewissen Grad.
Es hängt eher davon ab, was die codes sind und wie viele es sind. Gute Compiler haben verschiedenen tricks, die Sie verwenden, zu optimieren, switch-Anweisungen, von denen Sie sich nicht beschäftigen mit gerade wenn/dann-Aussagen. Die meisten sind helle genug zu tun, einfache Mathematik, oder verwenden Sie " suchen/springen-Tabellen für den Fall, 0, 1, 2 oder Fall 3, 6, 9 zum Beispiel.
Natürlich einige nicht, und viele sind leicht vereitelt durch ungewöhnliche oder unregelmäßige Werte. Auch wenn der code für das handling von mehrere Fällen sieht bemerkenswert ähnlich, cut und paste kann dazu führen, Probleme bei der Wartung. Wenn du viele codes, aber Sie können eingeteilt werden algorithmisch in Gruppen, Sie sollten erwägen, mehrere/geschachtelte switch-Anweisungen, zum Beispiel als:
Können Sie verwenden:
Viele Interpreter decodieren opcodes auf diese Weise, da eine single-byte-opcode kann zusätzliche information verpackt, in die verschiedene bits, und die Transkription aller möglichen Kombinationen und Ihre Handler wäre, sich wiederholende und zerbrechlich. Auf der anderen Seite, übermäßige etwas mangeln, kann die Niederlage der Optimierung durch den compiler und kontraproduktiv sein.
Es sei denn, Sie sind sicher, dass dies ist ein echtes performance-Engpass würde ich vermeiden, vorzeitige Optimierung: tun Sie es, egal welchen Weg schlägt Sie sich als ausreichend stabil und schnell zu implementieren. So und wenn Ihre Anwendung zu langsam läuft, Profil und optimieren Sie entsprechend.
Die switch-Anweisung schneller gehen würde, aber wenn dies nicht in Ihren Anwendungen zu Engpässen sollten Sie nicht wirklich Pflege darüber.
Gehen für das, was macht Ihren code leichter zu pflegen, auch langfristig.
Dein Beispiel ist zu kurz, um einen aussagekräftigen call-in dieser Hinsicht.
Ich bin teilweise zu lookup-Tabellen für mich, weil ungewöhnlich lange switch-Anweisungen scheinen mich zu verwechseln, die eine Trennung zwischen code und Daten. Ich denke auch Tabellen eignen sich besser auf zukünftige änderungen und Wartung.
Alles IMHO natürlich.
Schlage ich vor, mit einer statischen, Konstanten, Tabelle von Paaren. Dies ist eine andere form der look-up-Tabelle:
Einen Vorteil zu diesem ist, dass die Tabelle erzeugt wird zur compile-Zeit, im Gegensatz zu einem
std::map
die initialisiert werden müssen, während der Laufzeit. Wenn die Mengen groß sind, könnten Siestd::lower_bound
, den Eingang zu finden, vorausgesetzt, der Tisch ist bestellt.Ein weiterer Vorteil dieser Technik ist Daten-getrieben. Die Werte können sich ändern, ohne änderungen an der Suchmaschine. Änderungen an code oder Prozess erfordern schwere regression-Tests, die Daten aber änderungen können nicht; YMMV.
Dies ist ähnlich zu dem, was ein compiler generieren könnte.
Wenn Sie verwenden können, tr1, die Sie nutzen könnten unordered_map, um die hash-Werte (hashing int-Werte können sehr schnell zu), die meisten lookups Konstante Zeit.
Jedoch, es sei denn, Sie haben die profiling-Daten zeigen, dass diese einen Engpass in Ihrem Programm-code in den Ansatz, der am meisten Sinn macht, von einem design-Standpunkt.
Ich sage anzeigen, wenn alle Sie tun, ist die Zuweisung eines Wertes. Mein Grund ist, dass es erweiterbar ist, ohne code ändern, die switch-Anweisung nicht.
btw, wie wäre es mit einem enum?
Ich denke, dass der generierte code der switch-case-Struktur können wachsen ziemlich groß, wenn die Menge des "codes" wird zu groß, in dem Fall denke ich, die stl::map ist besser geeignet.
Normalerweise würde ich vorschlagen, eine Karte oder ein lookup-array oder vielleicht sogar einige hybrid-lookup-monster (unter der Annahme, dass Sie für die Geschwindigkeit zu optimieren oder code-Größe, anstatt die Lesbarkeit natürlich), aber es ist erwähnenswert, dass der neue GCC Versionen sind intelligent genug, um zu ersetzen switch/case " - Anweisungen wie diese lookup-Tabellen. Zwar ist dies nicht so toll für die ganz lichten Schlüssel kann es werden, wenn Sie Tasten sind in Büscheln wie:
0, 1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 193, 194, 195, 196, 197, 198...
Natürlich, wenn Sie es möglicherweise gern einige arithmatic, um die Konvertierung zu tun, noch besser (in der Regel). Nie übersehen, verschieben, vertauschen, endianness, oder mehr die traditionelle Mathematik, wenn etwas wie das zu tun.
unordered_map wahrscheinlich besser geeignet, da hier, wie es mit hash-Tabelle und lookup wird wirklich schneller statt Schalter.