Array in Ausdruch erzeugen
-
Hi Forum,
Gibt es eine Möglichkeit folgenden Code zu verkürzen?
int array[] = {1, 2, 3}; myfunc(array);Ich hatte da an eine solche Variante gedacht: (die aber leider nicht geht)
myfunc({1, 2, 3});Mfg X4rd3n
-
Nein. Das nennt sich Initialisierungsliste und wird nur benötigt, um Arrays (und POD-Structs) zu initialisieren. Es gäbe vielleicht eine Methode mit Überladung des Komma-Operators oder Funktionen mit variabler Anzahl Argumente, aber das sind beides sehr hässliche und fehleranfällige Varianten.
Abgesehen davon sollte man sowieso keine Arrays übergeben (zumindest nicht ohne Grössenangabe). Benutz doch STL-Container.
-
Soweit ich weiß müsste bei STL-Containern doch auch den Umweg über die Variable machen oder?
Längenangabe für das Array brauch ich nicht weil es immer gleich lang ist.
-
x4rd3n schrieb:
Soweit ich weiß müsste bei STL-Containern doch auch den Umweg über die Variable machen oder?
Ja. Man könnte zwar schon eine Frickelei mit temporären Objekten machen, aber das lohnt sich nicht (es sei denn, du benötigst nur einen der Containerkonstruktoren, z.B. für 5 gleiche Elemente). Was ist überhaupt so schlimm daran? Dass man es in Java kann und in C++ nicht? Falls ja, solltest du deine Einstellung von Grund auf ändern...
x4rd3n schrieb:
Längenangabe für das Array brauch ich nicht weil es immer gleich lang ist.
Wenn du die Längenangabe sowieso schon weisst, wieso machst du nicht eine Funktion mit genau so vielen Parametern?
-
Nexus schrieb:
x4rd3n schrieb:
Soweit ich weiß müsste bei STL-Containern doch auch den Umweg über die Variable machen oder?
Ja. Man könnte zwar schon eine Frickelei mit temporären Objekten machen, aber das lohnt sich nicht (es sei denn, du benötigst nur einen der Containerkonstruktoren, z.B. für 5 gleiche Elemente). Was ist überhaupt so schlimm daran? Dass man es in Java kann und in C++ nicht? Falls ja, solltest du deine Einstellung von Grund auf ändern...
Ich wollte mir halt die Arbeit sparen mir jedesmal neue Namen für das Array ausdeken zu müssen. Auch würde beim Umweg über die Initialiesierung auch jedesmal ein bisschen Speicherplatz belegt werden oder?
Nexus schrieb:
x4rd3n schrieb:
Längenangabe für das Array brauch ich nicht weil es immer gleich lang ist.
Wenn du die Längenangabe sowieso schon weisst, wieso machst du nicht eine Funktion mit genau so vielen Parametern?
Bei einem Array kann ich leichter mit optionalen Parameter arbeiten :).
-
void foo(int* arr){ for(int i=0; i<5; ++i) std::cout << arr[i] << std::endl; } foo((int[]){1,2,3,4,5});
-
Super, Danke! Es geht!
-
dann noch ein makro definieren für die schreibfaulen und dann sieht es aus wie dein plan...
und öffnet neuen fehlerquellen tor und tür...:D *duckundweg*
-
Versuch mal ein bisschen genauer zu argumentieren, wenn überhaupt weißt, wovon du da sprichst.
-
user13 schrieb:
void foo(int* arr) //... foo((int[]){1,2,3,4,5});Hach wie ich solchen Code doch liebe... ups ein , vergessen...
foo((int[]){1,2,3,45});Und schon hat man einen Fehler im Programm, den der Compiler wohl in der Regel nicht finden kann... Und damit meine ich nicht einfach das es ein Wertefehler ist (undefiniertes Verhalten trifft die Sache durchaus auf den Punkt).
cu André
-
Wobei ich mich generell frage, was die Motivation dahinter ist, alles in eine Zeile zu packen. In so einem Falle sollte man aber auch Makros so exzessiv wie möglich nutzen...
Wenn man sicher gehen will, dass das Array nachher nicht mehr existiert, weil es ja um die paar Byte schade sein könnte, kann man auch einen lokalen Block erstellen:
{ int Array[] = {3, 1, 5, 7, 9}; Function(Array); }Grundsätzlich wäre
std::vectorzwar sicherer, aber vielleicht für etwas konstantes, Datenbank-ähnliches nicht so komfortabel (zumal man für jedes Elementpush_back()aufrufen muss, wenn man nicht gerade mit Boost.Assign oder so arbeitet)...
-
[quote Nexus]Wobei ich mich generell frage, was die Motivation dahinter ist, alles in eine Zeile zu packen. In so einem Falle sollte man aber auch Makros so exzessiv wie möglich nutzen... [/quote]
Es gibt zwei Gruppen von Menschen:
die erste Gruppe würde "strcpy" implementieren als://... size_t length = strlen(quelle); for(size_t i=0; i<=length; i++) ziel[i] = quelle[i]; //...und die zweite Gruppe als:
//.. while(*ziel++ = *quelle++); //...Ein erfahrener C/C++-Programmierer würde wohl das zweite Beispiel vorziehen.
Und wenn es ausreichend übersichtlich ist, dann packt man auch Einiges in eine Zeile.@asc:
Na, das ist ja wunderbar. Dann halt:const unsigned SIZE = 5; foo( (int[SIZE]){1,2,3,4,5} );Und hättest du hier ein Problem gehabt, dann würdest du auch mit einem benamten Array dieses Problem haben.
-
user13 schrieb:
@asc:
Na, das ist ja wunderbar. Dann halt:const unsigned SIZE = 5; foo( (int[SIZE]){1,2,3,4,5} );Und hättest du hier ein Problem gehabt, dann würdest du auch mit einem benamten Array dieses Problem haben.
Dann passen wir jetzt mal foo an, das es mit 6 Parametern arbeiten kann. Und ja, ich würde garnicht zum C-Array greifen. Die STL und TR1 bieten sicherere Alternativen. Sei es nun std::vector oder std::tr1::array.
cu André
-
user13 schrieb:
Ein erfahrener C/C++-Programmierer würde wohl das zweite Beispiel vorziehen.
Und das aus gutem Grund. Der allerdings nicht darin besteht, dass die zweite Variante in eine Zeile passt. Das ist ein netter Nebeneffekt. Hauptgrund ist die höherere Performance. Wenn die Performance der ersten Variante höher wäre, dann wäre strcpy auch so implementiert, unabhängig davon ob's dafür mehr Zeilen braucht.
-
@ user13:
Netter Trick mit demstrcpy(). Nur kommt man glaube ich selten auf die Idee, zuerst mitstrlen()die Länge abzufragen, um dann nochmals alle Zeichen bis zum '\0' durchzuiterieren. Mich wundert es eigentlich, dass du nicht auf die Idee gekommen bist,strlen(quelle)gerade in den Schleifenkopf zu schreiben.Womit schon wieder eine Zeile wegfallen würde.
Und was das Standardargument Performance betrifft: Woher weisst du, wie viel es ausmacht, wenn man zuerst ein Objekt erzeugt und dann dieses übergibt? Bzw. ob es überhaupt was ausmacht?
Naja, hier finde ich "premature optimization is the root of all evil in programming" ganz passend... Es gibt leider einfach zu viele Leute, die für einige Nanosekunden die Sicherheit und Übersichtlichkeit des Codes aufs Spiel setzen. Schau doch nur mal die C++-Streams an, die sind nicht gerade performant. Es ist aber auch jedem überlassen,
printf()und Co. zu verwenden...
-
Also gut. Ich will nicht von jedem in einen Disput verwickelt werden.
Und was das Standardargument Performance betrifft: Woher weisst du, wie viel es ausmacht, wenn man zuerst ein Objekt erzeugt und dann dieses übergibt? Bzw. ob es überhaupt was ausmacht?
Ich bin in keinem meiner Beiträge auf die Performance eingeganen, sondern auf die Prägnanz.
Die Beispiele sollten nur klar machen, dass man statt "lang und übersichtlich" wohl eher "kurz und übersichtlich" nehmen würde. Ich wollte gar nicht auf die Performance eingehen, da würe ich eher etwas in Richtung Duff's device nehmen, wenn sie gefordert wird.
Na dann halt so:entweder: //.. while(*quelle != '\0'){ *ziel = *quelle; *ziel++; *quelle++; } *ziel = '\0'; //... oder: //.. while(*quelle != '\0'){ *ziel++ = *quelle++; } *ziel = '\0'; //... oder: //.. size_t i; for(i=0; quelle[i]!='\0'; i++) ziel[i] = quelle[i]; quelle[i] = '\0'; //.. und nocht tausende weitere, wenn ihr wollt...... oder letzten Endes: //.. while(*ziel++ = *quelle++); //...Was jetzt? Irgendwelche Performance Unterschiede? Wohl eher nicht.
Und? Was werdet ihr nehmen? Klar, einfach std::string, oder? Aber davon haben wir gar nicht gesprochen.Das Problem ist:
Gibt es eine Möglichkeit folgenden Code zu verkürzen?int array[] = {1, 2, 3}; myfunc(array);Ja.
Mein Vorschlag war:myfunc( (int[3]){1, 2, 3} );1. Das Problem wurde behoben: der Code ist kürzer geworden.
2. Ist der Code übersichtlich genug: ja, ja und noch mal ja.
3. Hätte die Ausführung des zweiten Fragments irgendwelche Laufzeitnachteile oder -vorteile gegenüber dem ersten: nein, jedenfalls sehe ich keine. Ein Array wird erzeugt, übergeben und danach zerstört. Der Unterschied ist bloß, dass im ersten Fragment ein benamter, im zweiten ein unbenamter Array erzeugt wird.Das allgemeine Problem, dass man die Arraygröße bereits zur Compilerzeit wissen muss, um keine Fehler zu begehen, ist mir selbstverständlich bewußt. Dass in vielen Situationen Container die bessere Alternative zu Arrays sind, ist klar. Aber bei diesem Problem ist es nicht der Fall. Und eure kurze Sichtweise, dass man überall dort Container verwendet soll, wo es auch geht, ist falsch. C++ unterstützt viele Paradigmen. Bloß weil ihr euch nur auf eine stützt, macht aus euch keine besseren Programmierer.
Ich weiß nicht, was ihr jetzt noch ausdenken werdet. Jedenfalls behaupte ich nicht, dass man überall, wo es nur geht, diese unbenamte Array verwendet soll. Sondern nur dort, wo sie auch angebracht sind. Bei diesem Problem ist es der Fall gewesen.
Ich bin kein "eine Zeile"-Freak. Ich strukturiere meinen Code so übersichtlich wie es nur geht. Bei diesem Problem benutze ich einen unbenamten Array. Und ich glaube, viele würden das auch so machen. Schließlich gibt's noch Kommentare.
Wie dem auch sei, mein Vorschlag ist besser als eure.Überzeugt mich, dass ich mich irre.
-
Hört! Hört! Das musste (wirklich) mal gesagt werden!

-
user13 schrieb:
Und eure kurze Sichtweise, dass man überall dort Container verwendet soll, wo es auch geht, ist falsch. C++ unterstützt viele Paradigmen. Bloß weil ihr euch nur auf eine stützt, macht aus euch keine besseren Programmierer.
Ich halte mich tatsächlich aus einen Grund als besseren Programmierer:
Ich versuche Code zu schreiben der auch die nächste Wartung überstehen kann, und nicht so leicht unnötige Fehlerquellen einbaut, die man erst schwer zur Laufzeit ausmachen kann. Ich habe Compilerfehler lieber als laufzeitfehler.// Getestet unter Visual C++ Express Edition, Servicepack 1 #include <array> #include <iostream> void foo(std::tr1::array<int, 5> const & arr) { for(std::tr1::array<int, 5>::const_iterator it=arr.begin(), end=arr.end(); it!=end; ++it) std::cout << (*it) << std::endl; } int main() { std::tr1::array<int, 5> arr = {1,2,3,4,5}; foo(arr); }Der Code ist nun etwas länger, aber wenigstens bekommt man einen Fehler, wenn man jetzt die Funktion anpasst und statt 5 nun z.B. 10 Werte benötigt.
-
user13 schrieb:
...
Das allgemeine Problem, dass man die Arraygröße bereits zur Compilerzeit wissen muss, um keine Fehler zu begehen, ist mir selbstverständlich bewußt. Dass in vielen Situationen Container die bessere Alternative zu Arrays sind, ist klar. ...Und woher soll der geneigte Leser hier wissen, was Dir "selbstverständlich" und "klar" ist ?
Du (bzw. jemand, der den jederzeit frei verfügbaren Nick "user13" genutzt hat) hast hier unkommentiert ein "unübliches" Stückchen Code in die Runde geworfen - als Antwort auf die Frage eines (vermeindlichen) Anfängers (zumindestens lässt die Syntaxfrage das vermuten).=> Du hast am falschen Ende gespart (oder wolltest eigentlich nur eine Diskussion über Deine Kompetenz initiieren).
Gruß,
Simon2.
-
Simon2 schrieb:
user13 schrieb:
...
Das allgemeine Problem, dass man die Arraygröße bereits zur Compilerzeit wissen muss, um keine Fehler zu begehen, ist mir selbstverständlich bewußt. Dass in vielen Situationen Container die bessere Alternative zu Arrays sind, ist klar. ...Und woher soll der geneigte Leser hier wissen, was Dir "selbstverständlich" und "klar" ist ?
Du (bzw. jemand, der den jederzeit frei verfügbaren Nick "user13" genutzt hat) hast hier unkommentiert ein "unübliches" Stückchen Code in die Runde geworfen - als Antwort auf die Frage eines (vermeindlichen) Anfängers (zumindestens lässt die Syntaxfrage das vermuten).=> Du hast am falschen Ende gespart (oder wolltest eigentlich nur eine Diskussion über Deine Kompetenz initiieren).
Gruß,
Simon2.
Weil ja jeder anfänger mit
// Getestet unter Visual C++ Express Edition, Servicepack 1 #include <array> #include <iostream> void foo(std::tr1::array<int, 5> const & arr) { for(std::tr1::array<int, 5>::const_iterator it=arr.begin(), end=arr.end(); it!=end; ++it) std::cout << (*it) << std::endl; } int main() { std::tr1::array<int, 5> arr = {1,2,3,4,5}; foo(arr); }direkt was anfangen kann...
-
... sofern er sich ganz kurz mit der syntax der Container und ihrer Funktionen auseinandersetzt. ja ?
Kann ich als Anfänger bestägigen