Ich neige dazu, varargs zu vermeiden, außer in einem bestimmten Fall, wo es sehr nützlich ist. Variable Argumente bieten nicht wirklich einen großen Nutzen, der über das hinausgeht, was durch einzelne Funktionsaufrufe erreicht werden kann, insbesondere in Ihrem Fall.
In Bezug auf die Lesbarkeit (und das ist in der Regel das, was ich über rohe Geschwindigkeit außer in sehr speziellen Fällen bevorzuge), gibt es keinen wirklichen Unterschied zwischen den folgenden zwei Optionen (ich habe eine Zählung zu den varargs Versionen hinzugefügt, da Sie entweder eine Zählung oder Sentinel benötigen, um das Ende der Daten zu erkennen):
update(2, FIELD_NAME1, 10, FIELD_NAME2, 20);
update(3, FIELD_NAME3, 10, FIELD_NAME4, 20, FIELD_NAME5, 30);
/* ========== */
update(FIELD_NAME1, 10);
update(FIELD_NAME2, 20);
update(FIELD_NAME3, 10);
update(FIELD_NAME4, 20);
update(FIELD_NAME5, 30);
Da die varargs-Version länger wird, müssen Sie sie aus Gründen der Formatierung ohnehin aufteilen:
update(5,
FIELD_NAME1, 10,
FIELD_NAME2, 20,
FIELD_NAME3, 10,
FIELD_NAME4, 20,
FIELD_NAME5, 30);
Die Methode "ein Aufruf pro Feldname" führt zu einem einfacheren Code in der Funktion selbst und beeinträchtigt nicht die Lesbarkeit der Aufrufe. Außerdem kann der Compiler auf diese Weise bestimmte Fehler erkennen, was bei varargs nicht möglich ist, z. B. falsche Typen oder eine Abweichung zwischen der vom Benutzer angegebenen und der tatsächlichen Anzahl.
Wenn Sie wirklich muss eine einzige Funktion aufrufen zu können, würde ich mich dafür entscheiden:
void update (char *k1, int v1) {
...
}
void update2 (char *k1, int v1, char *k2, int v2) {
update (k1, v1);
update (k2, v2);
}
void update3 (char *k1, int v1, char *k2, int v2, char *k3, int v3) {
update (k1, v1); /* or these two could be a single */
update (k2, v2); /* update2 (k1, v1, k2, v2); */
update (k3, v3);
}
/* and so on. */
Sie könnten die höheren Funktionen sogar als Makros ausführen, ohne die Typsicherheit zu verlieren.
Der einzige Ort, an dem ich dazu neige, varargs-Funktionen zu verwenden, ist, wenn ich die gleiche Funktionalität wie printf()
- Ich musste zum Beispiel gelegentlich Protokollierungsbibliotheken mit Funktionen wie logPrintf()
die die gleiche Funktionalität bieten. Ich kann mir nicht vorstellen, dass jede In meiner langen (und ich meine wirklich langen :-) Zeit an der Front habe ich es noch kein einziges Mal benutzen müssen.
Nebenbei bemerkt, wenn Sie sich für die Verwendung von varargs entscheiden, neige ich dazu, eher sentinels als counts zu verwenden, da dies Fehlanpassungen beim Hinzufügen von Feldern verhindert. Man könnte leicht vergessen, die Zählung anzupassen, und am Ende steht man da:
update (2, k1, v1, k2, v2, k3, v3);
beim Addieren, was heimtückisch ist, weil es k3/v3 stillschweigend überspringt, oder:
update (3, k1, v1, k2, v2);
beim Löschen, was mit ziemlicher Sicherheit fatal für die erfolgreiche Ausführung Ihres Programms ist.
Ein Wächter verhindert dies (natürlich nur, wenn man den Wächter nicht vergisst):
update (k1, v1, k2, v2, k3, v3, NULL);