Stilfrage: for-Schleife mit "Sonderbehandlung"
-
Ich habe folgendes Szenario: ich will in einer Schleife ueber einen Parameter laufen. Fuer eine Handvoll dieser Parameter muss ich eine Sonderbehandlung machen an Stelle der "normalen" Behandlung. Mir fallen jetzt verschiedene Alternativen ein:
//vorgegeben: const int fallA[3] = {2,6,7}; const int fallB[3] = {1,5,11}; void BehandlungA(int i); void BehandlungB(int i); for (int i = 0; i < imax; ++i) { //Variante A, b, oder c? }Variante A
switch(i) { case 2: case 6: case 7: BehandlungA(i); break; case 1: case 5: case 11: BehandlungB(i); break; default: /*...*/ }Variante B
if (std::find(fallA, fallA+3, i) != fallA+3) BehandlungA(i); continue; if (std::find(fallB, fallB+3, i) != fallB+3) BehandlungB(i); continue; /*...*/Variante C
if (std::find(fallA, fallA+3, i) != fallA+3) BehandlungA(i); else if (std::find(fallB, fallB+3, i) != fallB+3) BehandlungB(i); else { /*...*/ }Welche der drei wuerdet ihr vorziehen - oder gibts noch eine andere, bessere?
-
Hmm, mich würde mal interessieren, ob dieses "fall-through" in Variante a effizienter ist als eine OR-Verknüphung.
-
ich würde es mit variante b machen. Lässt sich auch einfach mit neuen parametern erweitern. Falls es sich als flaschenhals zeigt, dann variante A.
Variante C find ich nicht toll. Mahct zwar das gleiche, aber durch das continue sieht man besser, das wirklcih nur das eine gemacht werden soll.
__stefan__: ich denk, das switch ist mindestens genauso schnell, vielleicht schneller. Aber das macht glaub ich im endeffekt fast nix aus
-
Ich würds davon abhängig machen, ob sich die Werte für die Sonderbehandlung ändern oder ob die für alle Zeiten fest sind. Wenn sie fest sind, würd ich einfach ein if(i == X || i == Y || i == Z) machen, da der Code mMn am einfachsten wär.
Wenn sich die Werte ändern können, würd ich Variante C mit find oder einer Prädikat Funktion nehmen.
-
Variante B funktioniert nur nicht.

Denn dank fehlender Klammerung wird das erste continue immer ausgeführt.
Wenn es um Performanz geht, lass die Schleife weg und schreib die Anweisungen hintereinander. Dann sparst du dir jede Verzweigung.
-
Ich habs jetzt mit Variante B (und natürlich richtiger Klammersetzung) gemacht. Die Schleife aufzudröseln kommt für mich weniger in Frage, da es momentan schon über 25 indizes geht, später vermutlich mehr.
-
Wie waer's mit Functionpointern? Wenn es viele verschiedene Sonderfaelle gibt wuerd ichs wahrscheinlich so (bzw. so aehnlich) loesen:
typedef void (*Function)(int i); typedef std::map<int, Function> FunctionMap; int main() { const int fallA[3] = {2,6,7}; const int fallB[3] = {1,5,11}; FunctionMap functionMap; for (int i = 0; i < 3; ++i) functionMap[fallA[i]] = &BehandlungA; for (int i = 0; i < 3; ++i) functionMap[fallB[i]] = &BehandlungB; for (int i = 0; i < 11; ++i) { FunctionMap::iterator iter = functionMap.find(i); if( iter != functionMap.end() ) iter->second(i); else cout << "Defaultbehandlung\n"; } return 0; }EDIT: du koenntest natuerlich auch alle moeglichen Indexe mit allen Behandlungsfunktionen in die Map stecken (bzw. in dem Fall dann eher ein Array machen), dann wird die for-Schleife sehr kurz & elegant, da du nicht ueberpruefen musst ob der Index in der Schleife ist, ausserdem waer die Variante dann sehr schnell... aber k.A. ob das jetzt nicht schon zuviel des Guten ist
Wenn es wirklich nur die 2 Sonderbedingungen gibt, ist deine Variante B IMO auch schon relativ nett.
-
es gibt genau die zwei Sonderbedingungen, kene mehr - aber danke für die Bemühungen.
-
warum so kompliziert? einfach in die schleife nen if(1 || 2 || 3) einbauen und fertig. wenn imax wesentlich größer als 11 werden kann, mach zwei schleifen draus. die erste geht bis min(11, imax), die zweite bis imax und verzichtet auf die conditionals. das ist übersichtlich und performant genug.