int a[variable]; ???!
-
rüdiger schrieb:
Z schrieb:
rüdiger schrieb:
Aus gutem Grund wird es das aber nicht in C++ geben.
Aus welchem Grund? Ich finde so ein Feature nicht schlecht. Das wäre wie ein new ohne delete[].
Das Feature ist schlecht, weil es keinen Weg gibt zu überprüfen ob überhaupt noch genug Speicher auf dem Stack vorhanden ist und es gibt keinen Weg den Fehlerfall zu behandeln.
Ich muss zugeben, dass es auf den ersten Blick gut wirkt. Aber es ist im Endeffekt doch ziemlich böse und alles andere als trivial.Jedes Feature kann man falsch verwenden. Ich stehe mehr auf dem Standpunkt, ein Arsenal von Features zu haben, aus denen man sich für den jeweiligen Fall die Mischung zusammenstellen kann. Sonst können wir gleich nur noch in Java oder C# programmieren.

-
Bjarne's C++0x FAQ:
C99 features:
...
- Not VLAs (Variable Length Arrays; thank heaven for small mercies).klingt so, als wäre er froh, dass VLAs nicht dabei sind. Richtig überzeugende Gründe fallen mir aber für keine Position ein. Es ist ja immer eine Kosten/Nutzen-Rechnung. VLAs müssen sich durch Sonderregeln, Komplexität, Inkonsistenzen erkauft werden. Lohnt sich das?
- sizeof würde kein reiner Compile-Zeit-Mechanismus mehr bleiben
- Was ist der Typ eines VLAs? Ist er unvollständig?
- Wie ist das Zusammenspiel mit Templates? (zB bzgl argument deduction, ...)
-
volkard schrieb:
rüdiger schrieb:
Der Code den er dafür generiert, sollte das zur Laufzeit überprüfen.
Das halte ich für irrelevant. Natürlich knallt man noch nicht megabytegroße Sachen auf den Stack. Stacküberlauf macht eben Programmabsturz. Damit hatte ich noch nie Probleme. Ich kann mir nicht vorstellen, daß jemand damit Probleme hat.
Jemand hat spätestens Probleme damit, wenn der Stack manchmal überläuft und manchmal nicht, je nach Benutzereingabe (und das am besten schon beim Kunden
).
-
Z schrieb:
Jedes Feature kann man falsch verwenden. Ich stehe mehr auf dem Standpunkt, ein Arsenal von Features zu haben, aus denen man sich für den jeweiligen Fall die Mischung zusammenstellen kann. Sonst können wir gleich nur noch in Java oder C# programmieren.

Klar kann man jedes Feature falsch verwenden. Es gibt aber auch Features die man bestenfalls nur sehr schwer richtig verwenden kann, und dazu gehören die gesamten dynamisch veränderlichen und nicht überprüfbaren Giftmüllexporte aus C-Beständen, wie z.B. die Funktionen der printf-Familie, die keinen Längencheck eingebaut haben, VLAs, variable Argumentlisten, diverse void-Pointer-Frickeleien usw.
Mehr Features sind durchaus nicht schlecht, wenn sie einen erkennbaren VOrteil bringen. Mehr Features sind aber dann schlecht, wenn sie nur einen kleinen Vorteil bringen und auf Kosten des wichtigsten Features überhaupt gehen: Der Sicherheit.
-
_matze schrieb:
volkard schrieb:
rüdiger schrieb:
Der Code den er dafür generiert, sollte das zur Laufzeit überprüfen.
Das halte ich für irrelevant. Natürlich knallt man noch nicht megabytegroße Sachen auf den Stack. Stacküberlauf macht eben Programmabsturz. Damit hatte ich noch nie Probleme. Ich kann mir nicht vorstellen, daß jemand damit Probleme hat.
Jemand hat spätestens Probleme damit, wenn der Stack manchmal überläuft und manchmal nicht, je nach Benutzereingabe (und das am besten schon beim Kunden
).Dann ist er dumm und hat es verdient.
Mit solchen Argumenten kannst Du auch Zeiger abschaffen und alles über Referenzen machen wollen. Oder delete abschaffen und einen garbage collector einführen.
Außerdem lege ich jetzt aus Trotz immer 10000-große Arrays auf den Stack und bekomme endlich auch mal einen Ausstieg, wenn der Stack alle ist, und zusätzlich einen, wenn mehr als 10000 Elemente gebraucht werden.Stellt euch mal vor, ich hätte eine Template-Klasse, die automatisch die Arrays, die mehr als 1000 Bytes belegen, im Freispeicher anlegt. Muß man da jetzt noch Angst haben? Klar, bei 900 rekursiven Aufrufen wirds langsam eng; aber das zusammen tut echt keiner.
-
volkard schrieb:
Stellt euch mal vor, ich hätte eine Template-Klasse, die automatisch die Arrays, die mehr als 1000 Bytes belegen, im Freispeicher anlegt. Muß man da jetzt noch Angst haben? Klar, bei 900 rekursiven Aufrufen wirds langsam eng; aber das zusammen tut echt keiner.
Naja - aber das kann man auch bisher schon mehr oder weniger - wenn man nen eigenen allocator schreibt, kann man das (mit 1 oder 2 krücken) auch mit ner (zur compilezeit bekannten) konstanten nachbauen...
hab ich auch schon gemacht - kann man eben bis zu ner größe von x bytes den stack nehmen und eben fest die x bytes auf dem stack allozieren - und nur ansonsten halt den heap nutzen...
bequem ist das leider nicht ganz - dafür aber sicher...bb
-
_matze schrieb:
volkard schrieb:
rüdiger schrieb:
Der Code den er dafür generiert, sollte das zur Laufzeit überprüfen.
Das halte ich für irrelevant. Natürlich knallt man noch nicht megabytegroße Sachen auf den Stack. Stacküberlauf macht eben Programmabsturz. Damit hatte ich noch nie Probleme. Ich kann mir nicht vorstellen, daß jemand damit Probleme hat.
Jemand hat spätestens Probleme damit, wenn der Stack manchmal überläuft und manchmal nicht, je nach Benutzereingabe (und das am besten schon beim Kunden
).int foo(unsigned long n) { int a = rand(); if (n = 0) return; cout << "Das Problem gibts schon und niemand stoerts " << a << '\n'; foo(n - 1); } int main() { unsigned long n; cin << n; foo(n) }
-
pumuckl schrieb:
Mehr Features sind durchaus nicht schlecht, wenn sie einen erkennbaren VOrteil bringen. Mehr Features sind aber dann schlecht, wenn sie nur einen kleinen Vorteil bringen und auf Kosten des wichtigsten Features überhaupt gehen: Der Sicherheit.
Das sehe ich völlig anders. Was ich an C++ sehr schätze, ist die Fülle an Features und dass C++ den Programmierer nicht für unmündig erklärt. "Sicherheit" um jeden Preis hast Du z.B. bei Java, dafür ist Java umständlich, ausdrucksschwach und im Vergleich zu C++ langsam in der Ausführung. Ich möchte so eine Sprache nicht gegen C++ tauschen.
Bei sachgemässer Anwendung machen VLAs keine Probleme. Sie fordern ausserdem nicht mehr Aufmerksamkeit vom Programmierer als andere C++ Features oder C++ an sich. VLAs würden gut zu C++ passen, aber was nicht ist, das ist nicht.

-
Blue-Tiger schrieb:
_matze schrieb:
volkard schrieb:
rüdiger schrieb:
Der Code den er dafür generiert, sollte das zur Laufzeit überprüfen.
Das halte ich für irrelevant. Natürlich knallt man noch nicht megabytegroße Sachen auf den Stack. Stacküberlauf macht eben Programmabsturz. Damit hatte ich noch nie Probleme. Ich kann mir nicht vorstellen, daß jemand damit Probleme hat.
Jemand hat spätestens Probleme damit, wenn der Stack manchmal überläuft und manchmal nicht, je nach Benutzereingabe (und das am besten schon beim Kunden
).int foo(unsigned long n) { int a = rand(); if (n = 0) return; cout << "Das Problem gibts schon und niemand stoerts " << a << '\n'; foo(n - 1); } int main() { unsigned long n; cin << n; foo(n) }
Das ist der Grund, warum Rekursion eher vermieden werden sollte, wenn die Anzahl der Rekursionen eventuell sehr groß werden kann. Ja, das Problem gibt's schon, aber das es niemanden stört, würde ich so nicht unterschreiben (vor allem die, die drauf reinfallen).

-
_matze schrieb:
Blue-Tiger schrieb:
_matze schrieb:
volkard schrieb:
rüdiger schrieb:
Der Code den er dafür generiert, sollte das zur Laufzeit überprüfen.
Das halte ich für irrelevant. Natürlich knallt man noch nicht megabytegroße Sachen auf den Stack. Stacküberlauf macht eben Programmabsturz. Damit hatte ich noch nie Probleme. Ich kann mir nicht vorstellen, daß jemand damit Probleme hat.
Jemand hat spätestens Probleme damit, wenn der Stack manchmal überläuft und manchmal nicht, je nach Benutzereingabe (und das am besten schon beim Kunden
).int foo(unsigned long n) { int a = rand(); if (n = 0) return; cout << "Das Problem gibts schon und niemand stoerts " << a << '\n'; foo(n - 1); } int main() { unsigned long n; cin << n; foo(n) }
Das ist der Grund, warum Rekursion eher vermieden werden sollte, wenn die Anzahl der Rekursionen eventuell sehr groß werden kann. Ja, das Problem gibt's schon, aber das es niemanden stört, würde ich so nicht unterschreiben (vor allem die, die drauf reinfallen).

Gib da mal 0 ein

Edit: Mal davon abgsehen das es gar nicht erst compileren sollte.

-
evilissimo schrieb:
_matze schrieb:
Blue-Tiger schrieb:
_matze schrieb:
volkard schrieb:
rüdiger schrieb:
Der Code den er dafür generiert, sollte das zur Laufzeit überprüfen.
Das halte ich für irrelevant. Natürlich knallt man noch nicht megabytegroße Sachen auf den Stack. Stacküberlauf macht eben Programmabsturz. Damit hatte ich noch nie Probleme. Ich kann mir nicht vorstellen, daß jemand damit Probleme hat.
Jemand hat spätestens Probleme damit, wenn der Stack manchmal überläuft und manchmal nicht, je nach Benutzereingabe (und das am besten schon beim Kunden
).int foo(unsigned long n) { int a = rand(); if (n = 0) return; cout << "Das Problem gibts schon und niemand stoerts " << a << '\n'; foo(n - 1); } int main() { unsigned long n; cin << n; foo(n) }
Das ist der Grund, warum Rekursion eher vermieden werden sollte, wenn die Anzahl der Rekursionen eventuell sehr groß werden kann. Ja, das Problem gibt's schon, aber das es niemanden stört, würde ich so nicht unterschreiben (vor allem die, die drauf reinfallen).

Gib da mal 0 ein

Edit: Mal davon abgsehen das es gar nicht erst compileren sollte.

Weshalb sollte es nicht kompilieren?
-
Da fehlt ein ;.
Im übrigen ist auch der Vergleich falsch.
-
int foo(unsigned long a) { /*...*/ if (n = 0) return; /*...*/ }!
bb
-
@unskilled
Warum hast du da den Funktionsnamen rausgenommen und durch einen Kommentar ersetzt?!
-
volkard schrieb:
_matze schrieb:
volkard schrieb:
rüdiger schrieb:
Der Code den er dafür generiert, sollte das zur Laufzeit überprüfen.
Das halte ich für irrelevant. Natürlich knallt man noch nicht megabytegroße Sachen auf den Stack. Stacküberlauf macht eben Programmabsturz. Damit hatte ich noch nie Probleme. Ich kann mir nicht vorstellen, daß jemand damit Probleme hat.
Jemand hat spätestens Probleme damit, wenn der Stack manchmal überläuft und manchmal nicht, je nach Benutzereingabe (und das am besten schon beim Kunden
).Dann ist er dumm und hat es verdient.
Mit solchen Argumenten kannst Du auch Zeiger abschaffen und alles über Referenzen machen wollen. Oder delete abschaffen und einen garbage collector einführen.Bei VLAs (zumindest wie in C99) gibt es aber keinen Weg sich abzusichern. Bei Zeigern kann man aktiv dafür sorgen, dass man Fehlerfälle vermeidet. Aber bei VLAs ist es in jedem Fall einfach gut Glück ob der Stack überläuft oder nicht.
Zumindest bräuchte man dann noch ein
stack_space_available()Gegenstück.
-
rüdiger schrieb:
Bei VLAs (zumindest wie in C99) gibt es aber keinen Weg sich abzusichern. Bei Zeigern kann man aktiv dafür sorgen, dass man Fehlerfälle vermeidet. Aber bei VLAs ist es in jedem Fall einfach gut Glück ob der Stack überläuft oder nicht.
Das ist es bei *jedem* Funktionsaufruf.
rüdiger schrieb:
Zumindest bräuchte man dann noch ein
stack_space_available()Gegenstück.Das wäre nett, aber auch keine Lösung. Es würde nur dazu verführen, solange noch viel Platz ist, Unfug zu treiben und die folgenden Funktionen abzuschnüren.
Netter finde ich Überlegungen der Art: Für eine VLA-Allokierung von 1000 Elementen brauche ich einen Takt, für dieselbe mit new brauche ich 100 Takte. Da ich alle Elemente später komplex anfassen werde, was mindestens 10 Takte braucht (ja nach Anwendung), bin ich bei nur 1% new-Overhead. An sich klares Votum vor new.
Außerdem geht Sicherheit vor. Wenn ich die Rekursionstiefe nicht abschätzen kann, gehe ich am besten zum Arzt und lass mich krankschreiben (je nach Arbeitgeber).
Wenn ich die Rekursionstiefe abschätzen kann, zum Beispiel sicherstellen kann, daß maxTiefe==32, dann habe ich nullinger schlechtes Gewissen, 4096 Bytes pro Rekursion auf den Stack zu legen. Und dabei weiß ich, daß ich im nur Subprozentbereich einspare.
Meine Container mit compilezeitbekannter Größe schalten bei 4096 um und ich finde, sie fühlen sich gut an.