C zu C++ - Einfacherer Übergang?
-
namespace invader schrieb:
Vor allem kann man mit finally auch für andere, die den Code später lesen, klar ausdrücken, dass dort Ressourcen freigegeben werden. Bei RAII-Frickeleien, eventuell auch mit zusätzlichen Scopes nur zu dem Zweck, ist das nicht so einfach verständlich.
Du biegst gerade das Problem, dass der Programmierer Nicht-Speicher-Ressourcen explizit freigeben muss, zu einem Vorteil um. Ist es wirklich besser, wenn man an Dinge wie Freigabe der angeforderten Ressourcen ständig denken und dafür Boilerplate-Code schreiben muss, der eh immer gleich aussieht? Sowas ist nämlich eine nicht zu unterschätzende Fehlerquelle.
namespace invader schrieb:
Das Problem sind [...] die aus C übernommenen Low-Level-Anteile, vor allem Zeiger die beliebig überall hin zeigen können. Die verhindern, dass man die ganzen schönen High-Level-Features unbesorgt nutzen kann; man muss immer die Low-Level-Ebene im Hinterkopf haben. C++ abstrahiert nicht davon, sondern versteckt nur ein paar Details. Also kein großer Vorteil zu C.
Das stimmt nun aber komplett nicht. C++ abstrahiert sehr wohl von Low-Level-Features. Natürlich geschehen hinter den Fassaden immer noch Low-Level-Operationen, aber für den Benutzer ist die Schnittstelle relevant.
Mittels RAII kann man zum Beispiel sehr schön manuelle Speicheranforderung umgehen. Oder mit überladenen Funktionen wird es möglich, ähnliche Aktionen gleich anzusprechen. Oder mit Templates erreicht man Typsicherheit und kann auf
void*
verzichten. Oder mit Laufzeitpolymorphie hat man implizite Type-Switches. Oder mit Operatorüberladung kann man benutzerdefinierte Typen analog zu BuiltIns verwenden.Was daran ist für dich keine Abstraktion?
namespace invader schrieb:
Ich halte es für sinnvoller, dass eine High-Level-Sprache z.b. einen Garbage Collector mitbringt, denn der ist auf dieser Ebene brauchbarer als C-Pointer.
Das sehen eben viele Leute anders. Ein GC hat auch Probleme, weil er keine deterministische Zerstörung garantiert. Oder weil man nicht weiss, wann er zum Zug kommt. Das sind alles Faktoren, die entscheidend sein können. Ich persönlich bin froh, hat C++ keinen GC. Und dennoch frickle ich nicht dauernd mit
new
unddelete
herum.
-
namespace invader schrieb:
Damit RAII das Problem löst, muss man aber Freigaben in Destruktoren verpacken (obwohl das in manchen Fällen gar nicht sinnvoll ist) und sich mit Smart Pointern rumschlagen (die nun wirklich ein hässlicher Workaround sind).
In Java wird das meiste Ressourcenhandling automatisch vom GC erschlagen, und für den Rest gibt es mit finally eine einfache und klare Lösung. Vor allem kann man mit finally auch für andere, die den Code später lesen, klar ausdrücken, dass dort Ressourcen freigegeben werden. Bei RAII-Frickeleien, eventuell auch mit zusätzlichen Scopes nur zu dem Zweck, ist das nicht so einfach verständlich.
Wie wir alle nicht das gute alte
finally { if(o!=null) { try { o.close(); } catch(Exception e) {} }
lieben...
RAII ist um laengen besser als finally. ein gc ist natuerlich auch super aber gc und raii sind keine sich widersprechenden konzepte. raii ist fuer jede art von resource gut, ein gc nur fuer rohen speicher.
ideal ist natuerlich ein gc und raii. nicht umsonst wird der GC in einigen Sprachen wie zB python oder C# durch eine schwache form von RAII unterstuetzt: dem konzept von "using". wo eine resource temporaer zu einem raii objekt gemacht werden kann.
krümelkacker schrieb:
Man muss kein ignoranter C++ fanboy sein, um diese Seite, die du gelinkt hast, schlecht zu finden.
Ich vermute doch. Wo finde ich denn Kritik an dieser Seite von Leuten, die C++ ebenso nicht sonderlich mögen?
Das macht keinen Sinn.
Warum sollte jemand der C++ nicht mag eine Seite kritisieren die C++ kritisiert? Genausowenig wirst du Kritik an Java Kritik von Java Kritikern finden.Lies mal zB comp.lang.c++.moderated oder so, dort sind wohl alle Punkte dieser troll-seite widerlegt worden. Natuerlich ist eine gewisse Kritik ja durchaus berechtigt. C++ hat eine Menge sachen die nicht ideal sind, Imperfect C++ ist zB ein gutes Buch dazu. Aber das meiste was man so liest ist eben nur getrolle.
-
Shade Of Mine schrieb:
Wie wir alle nicht das gute alte
finally { if(o!=null) { try { o.close(); } catch(Exception e) {} }
lieben...
Ein reines Syntax-Problem:
with open("in.txt") as infile: print(infile.read())
Wie heisst die Sprache?
-
mngbd schrieb:
Shade Of Mine schrieb:
Wie wir alle nicht das gute alte
finally { if(o!=null) { try { o.close(); } catch(Exception e) {} }
lieben...
Ein reines Syntax-Problem:
with open("in.txt") as infile: print(infile.read())
Wie heisst die Sprache?
Das war ein häßlichkeits-Beispiel aus der Java-Welt.
Nachdem du deinen Dateilese/schreibekram erledigt hast, musst du die Datei noch schließen (auch wenn ein Lese/Schreibfehler auftrat, deswegen im finally-Block). Aber erst einmal prüfen, ob es das Objekt überhaupt gibt (kann ja schon bei der Erzeugung eine Exception aufgetreten sein), dann musst du die Datei schließen - was ja auch eine Exception werfen kann, deswegen nochmal Block drum rum.
-
Nexus schrieb:
namespace invader schrieb:
Ich halte es für sinnvoller, dass eine High-Level-Sprache z.b. einen Garbage Collector mitbringt, denn der ist auf dieser Ebene brauchbarer als C-Pointer.
Das sehen eben viele Leute anders. [...] Ich persönlich bin froh, hat C++ keinen GC.
Ich auch. Und ich habe vorher 7 Jahre Java programmiert. Es ist einfach nicht das richtige Werkzeug für das, was ich jetzt mache. Ich entschloss mich, richtig C++ zu lernen (Bücher: TC++PL, EffC++) und bin von einigen Dingen (RAII) sehr positiv überrascht worden. Hat dann aber doch 'nen Jahr gedauert, bis ich Code produzieren konnte, der mir 2 Monate später noch gefällt.
@namespace invader: Wenn Du etwas anderes als C++ willst, nimmst Du auch etwas anderes als C++. So einfach ist das. Und vermeide es, von Dir auf andere zu schließen.
Shade Of Mine schrieb:
Wo finde ich denn Kritik an [Yossi's FQA] von Leuten, die C++ ebenso nicht sonderlich mögen?
Das macht keinen Sinn.
Warum sollte jemand der C++ nicht mag eine Seite kritisieren die C++ kritisiert? Genausowenig wirst du Kritik an Java Kritik von Java Kritikern finden.Das Problem liegt wohl auch darin, dass wahrscheinlich viele von denen, "die C++ ebenso nicht sonderlich mögen" entweder C++ nicht beherrschen und daher einen solchen Text nicht kritisieren können oder nicht zugeben würden, dass ein Text, der C++ einseitig darstellt und überdramatisiert, wirklich nicht so toll ist. Ich bezweifle nicht, dass es auch Ausnahmen gibt/geben kann. Aber die dürften schwer zu finden sein.
-
mngbd schrieb:
Ein reines Syntax-Problem:
with open("in.txt") as infile: print(infile.read())
Wie heisst die Sprache?
Das ist Python. Und ein kurzer Blick in die Doku offenbart, dass das File-Objekt von open() gleichzeitig ein Kontextmanager ist. Wenn der with-Block endet oder es einen Fehler gibt, wird autamatisch die __exit()__-Funktion des Kontextmanagers aufgerufen. Und das ist in etwa die Technik, die sich hinter RAII verbirgt.
Vergleiche:
fstream f("in.txt"); printfile(f);
Dass das Lesen des Dateiinhalts in C++ nicht mit einem .read() getan ist, ist ein anderes Problem.
-
XMaster schrieb:
Das ist Python. Und ein kurzer Blick in die Doku offenbart, dass das File-Objekt von open() gleichzeitig ein Kontextmanager ist. Wenn der with-Block endet oder es einen Fehler gibt, wird autamatisch die __exit()__-Funktion des Kontextmanagers aufgerufen. Und das ist in etwa die Technik, die sich hinter RAII verbirgt.
Genau. Aber äquivalent kann man in dem Fall auch sagen:
try: infile = open("in.txt") print(infile.read()) finally: if infile: infile.close()
Bei Interesse: http://www.python.org/dev/peps/pep-0343/
Aber eigentlich geht's ja nur um eine simple Syntax-Erweiterung. Darüber Jahre lang zu streiten finde ich ein wenig überzogen. Aber das muss man wahrscheinlich, weil Makros böse sind.
-
krümelkacker schrieb:
@namespace invader: Wenn Du etwas anderes als C++ willst, nimmst Du auch etwas anderes als C++. So einfach ist das. Und vermeide es, von Dir auf andere zu schließen.
Mach ich ja. Das kann ich aber umgekehrt auch zu den ganzen C++-Freunden hier sagen, die pausenlos C++ als viel besser als andere Sprachen darstellen.
Shade Of Mine schrieb:
Das Problem liegt wohl auch darin, dass wahrscheinlich viele von denen, "die C++ ebenso nicht sonderlich mögen" entweder C++ nicht beherrschen und daher einen solchen Text nicht kritisieren können
Naja ich denke, dass Leute, die C++ wirklich gut beherrschen, tendenziell eher C++ kritisch sind. "Von weitem" wirkt C++ ja schon ganz großartig, ich fand C++ auch toll, als ich es gelernt hab.
oder nicht zugeben würden, dass ein Text, der C++ einseitig darstellt und überdramatisiert, wirklich nicht so toll ist.
Kann natürlich sein.
Mag ja sein, dass das FQA stellenweise nicht ganz objektiv ist, aber wer den Text einfach als FUD und Getrolle abtut, ist IMHO eindeutig ein ignoranter C++-Fanboy
BTW, eben hieß es noch, dass C++ so wunderbar ist, weil es verschiedene Paradigmen unterstützt und man völlig frei jeweils die Features nutzen kann, die gerade am besten passen. Und jetzt wird plötzlich das RAII-Paradigma so gelobt, zu dem einen C++ alternativlos zwingt? Da werden ja sehr flexible Maßstäbe angesetzt.
Ich denke, diese ganze Diskussion hier bringt eh nichts.
-
namespace invader schrieb:
ich fand C++ auch toll, als ich es gelernt hab.
Fail. Du hast nie C++ gelernt.
-
Lustig, wie die C++-Jünger immer davon überzeugt sind, dass jeder, der etwas an ihrem geheiligten C++ zu kritisieren hat, ja ganz klar nichts davon verstehen kann. Oder gleich ein Troll ist.
-
Das ist doch alles blah, was von Dir kommt. Ich kann genauso gut den Spieß umdrehen und sagen: "Aber wer den Text [FQA] in einer Forum "Diskussion" als Negativbeispiel gegen C++ bringt, ist IMHO eindeutig ein ignoranter C++ hater." Oder "Lustig, wie Du davon überzeugt bist, dass jeder, der Dich oder Yossi's FQA kritisiert, ja ganz klar ein C++-Jünger oder C++-Fanboy sei."
... ist doch Murks alles ...
Wie schwer ist das denn zu verstehen: Die Welt ist noch so Schwarz/Weiß, wie Du sie haben willst. Der FQA Text ist einseitig, überdramatisierend und hauptsächlich nutzlos. Und keiner von uns, der das so sieht, vertritt die Meinung, dass C++ das beste sei "wo geht". Ich für meinen Teil kann über 20 Jahre Programmiererfahrung in diversen Sprachen zurückblicken, 8 Jahre davon zB in Java. Ich kenne also auch die "high level"- und "garbage collection"-Welt. Na und? Für das, was ich momentan mache, ist Java eben nicht zu gebrauchen. Wenn Du mit C++ nicht klar kommst, ist das nicht mein Problem. Habe ich gesagt, dass Java Scheiße ist? Nein, habe ich nicht. Du verwechselst da etwas. Es gibt Leute, die C++ einsetzen, weil's für ihre Anwendung ein gutes Werkzeug ist. Die sind nicht automatisch C++ fanboys. Klar, wenn einer Blödsinn über eine Sprache schreibt, von der ich behaupten würde, dass ich sie behersche, dann kann ich dagegen anstinken. Das gilt nicht nur für C++. Hab mich auch hier und da schon zu Wort gemeldet, um Java in Schutz zu nehmen. Das sind generell Situationen, wo jemand versucht, etwas über eine Sprache zu sagen, der aber davon keine Ahnung hat. Es geht nicht um die "einzige richtige Sprache". Es geht darum, mehrere zu beherrschen, ihre Vor- und Nachteile zu kennen, und für die jeweilige Anwendung die richtige Sprache auszuwählen. Wenn ich nichtlineare Gleichungssysteme mit über einer Milliarden Unbekannten lösen will, nehme ich bestimmt nicht Java, C#, Ruby, Python, etc. Dann nehme ich C++. Das versteht sich doch wohl von selbst.
-
namespace invader schrieb:
Lustig, wie die C++-Jünger immer davon überzeugt sind, dass jeder, der etwas an ihrem geheiligten C++ zu kritisieren hat, ja ganz klar nichts davon verstehen kann. Oder gleich ein Troll ist.
Auch wenn du das wie ein Mantra wiederholst, es stimmt dennoch nicht.
Nur weil wir nicht die selben Probleme sehen wie du sind wir noch lange nicht unkritisch. Lies einfach mal Imperfect C++ und dann reden wir weiter, ok?
-
namespace invader schrieb:
Blue-Tiger schrieb:
Reine Neugier: was waer denn ein Beispiel eines solchen Workarounds?
Na z.B. ist Exception Handling zusammen mit manueller Speicherverwaltung eine Blöde Idee, weil erzeugte Objekte nach einer Exception nicht freigegeben werden. In C++ sind daher Krücken wie RAII bzw. Smart Pointer notwendig.
Du solltest mal das Alter von C++ berücksichtigen. C++ ist in etwa 30 Jahre alt. Damals kannte man nicht viel besseres. Trotzdem wird C++ heute noch, trotz antiquierter Techniken wie RAII und Smartpointer, sehr oft und mit Erfolg eingesetzt.
-
zum Beispiel schrieb:
namespace invader schrieb:
Ich will, dass eine Sprache sich auf ein bestimmtes Paradigma festlegt,
[...]
Das ist natürlich ein Ideal, das praktisch wohl von keiner Sprache wirklich erreicht wird, aber IMHO ist C++ am weitesten davon entfernt.es gibt solche Sprachen: Forth, LISP, Haskell, Self, Smalltalk, APL ...
- die sind für gewöhnlich nur nicht so furchtbar beliebt. Dafür sind sie äußerst langlebig, weil unabhängig von Syntax-Mode-Erscheinungen etc
Lisp legt sich nicht auf ein Paradigma fest. Aber Einparadigma-Sprachen sind schon sehr anstrengend. Oft wird das dann zum idealen Beispiel für "Wenn man nur einen Hammer hat, dann sieht jedes Problem aus wie ein Nagel."
@Baba Yaga
GCs gibt es schon seit den 50ern oder 60ern. Wenn man will kann man ja auch einen GC für C++ benutzen. RAII ist aber sicher keine antiquierte Technik. Hat halt alles seine Nachteile. RAII kann jede Ressource freigeben, aber je nach Anforderungsschema kann RAII kompliziert werden.Was ich immer sehr lustig finde, dass so getan wird als sei Exceptionsicherheit ein exklusives Problem von C++. Dabei ist es ein Problem in jeder Sprache mit Exceptions. In C++ ist das Problem natürlich offensichtlicher, weil man in er Regel keinen GC verwendet.
@namespace invader
Java ist doch auch voller Workarrounds und veralteter Dinge. Das kommt einfach mit der Zeit. Java wird nun auch bald 20 Jahre alt.Vorallem findet man C++ in fast jeder Domäne. Die meisten anderen Sprachen sind dagegen eher beschränkt vom Einsatzgebiet. Daher muss man sich vorher auf einen Bereich festlegen, ansonsten geht das ganze ein bisschen ziellos in alle Richtungen. Sicher ist ein GC für bestimmte Anwendungen sehr erfreulich (btw. für C++ gibt es auch GCs), aber Leute aus anderen Bereichen (zB µCs oder Verarbeitung großer Datenmengen) fangen dann schon an zu stönen und man kommt einfach nicht weiter. Das ist eben das unfruchtbare an diesen ganzen Flamewars hier. Sich über spezifische Fehler in einer Sprache aufzuregen, die einfach die meisten Nutzer der Sprache nicht wirklich stören, ist ja wenig hilfreich. Die meisten Javaprogrammierer stören sich ja zB nicht an den kaputten Floatingpoints, weil sie einfach nicht viel mit Numerik am Hut haben. Andersrum stören sich C++ Programmierer auch selten an RAII oder an dem angeblich "defective Inlining" (um mal etwas aus der FQA zu nehmen).
-
namespace invader schrieb:
Damit RAII das Problem löst, muss man aber Freigaben in Destruktoren verpacken (obwohl das in manchen Fällen gar nicht sinnvoll ist) und sich mit Smart Pointern rumschlagen (die nun wirklich ein hässlicher Workaround sind).
Das ist keineswegs der Fall. Im Destruktor ist die Resourcenfreigabe schon an der richtigen Stelle, man muß sich natürlich Gedanken über die Lebensdauer des Objektes machen. Bei vielen Java Programmierern unterbleibt das - mit fatalen Konsequenzen.
namespace invader schrieb:
In Java wird das meiste Ressourcenhandling automatisch vom GC erschlagen,
Inkorrekt, nur Speicher läßt sich damit verwalten.
namespace invader schrieb:
und für den Rest gibt es mit finally eine einfache und klare Lösung.
Wie schreiben C Programmierer "… gibt es mit free eine einfache und klare Lösung" - lächerlich, da es unnötige Coderedumdanz und eine hohe Fehleranfälligkeit darstellt. Mit der Einführung des GC in Sprachen, meine erste GC Sprache war Oberon-2, wurde das Problem für Arbeitsspeicher gelöst, aber auch nur für Arbeitsspeicher. Alle anderen Resourcen muß man auch weiterhin händisch verwalten, und im Falle von Java muß man N finally Blöcke schreiben. Nervig, überflüssig, fehleranfällig. Dann lieber das Problem 1 mal in der Klasse lösen und nicht N mal bei der Nutzung der Klasse.
Über die Lebensdauer der Exemplare einer Klasse muß sich der Nutzer einer Klasse immer Gedanken mache, egal ob es Smalltalk, CLOS, Java, C++ oder was auch immer ist.
namespace invader schrieb:
Vor allem kann man mit finally auch für andere, die den Code später lesen, klar ausdrücken, dass dort Ressourcen freigegeben werden. Bei RAII-Frickeleien, eventuell auch mit zusätzlichen Scopes nur zu dem Zweck, ist das nicht so einfach verständlich.
Ach und bei GC soll das ganze auf einmal anders ablaufen? Entscheide dich mal für ein Vorgehen. Entweder ist die manuelle Freigabe von Resourcen schlecht, dann ist sie das immer, oder sie ist es nicht, dann solltest du auch keine Probleme mit malloc und free haben.
namespace invader schrieb:
… vor allem Zeiger die beliebig überall hin zeigen können.
Java krankt fast an dem gleichen Problem, Nullpointer Exceptions sind bei Java allgegenwertig, also muß man auch mit Java aufpassen, daß Zeiger (Referenzen sind ganz banale Zeiger, wie man sie von Pascal kennt) nicht in Nirwana weisen. Java kennt lediglich keine Pointerarithmetik, auf die man in vielen Sprachen ohne GC ebenfalls verzichtet hat: Pascal, Modula-II, Ada, Fortran, …
-
rüdiger schrieb:
Was ich immer sehr lustig finde, dass so getan wird als sei Exceptionsicherheit ein exklusives Problem von C++. Dabei ist es ein Problem in jeder Sprache mit Exceptions. In C++ ist das Problem natürlich offensichtlicher, weil man in er Regel keinen GC verwendet.
Bei C++ hast du halt 100 mal soviel Dinge, bei denen du eigentlich auf Exceptionsicherheit achten müsstest. Aber wer verwendet denn schon Exceptions in C++?
RAII finde ich eigentlich ziemlich genial. Ich hab noch keine bessere Methode gesehen, um Files wieder zu schließen oder ein Mutex wieder frei zu geben.
Was wirklich nervt an C++ ist, dass es nie eine vernünftige Standard Library mit ausreichendem Funktionsumfang hatte. Jetzt hat fast jede Library ihren eigenen String, eigene Thread usw. Dieses ganze konvertieren und zusammenfummeln von Libraries die nicht schön zusammen passen, bremst die Entwicklungsgeschindigkeit ungemein.
-
ort schreiben schrieb:
RAII finde ich eigentlich ziemlich genial. Ich hab noch keine bessere Methode gesehen, um Files wieder zu schließen oder ein Mutex wieder frei zu geben.
Ist es nicht. Ich möchte garnicht erst wissen, wie viele C++ Programme aus Unachtsamkeit ein File einige hundert mal öffnen und schließen, obwohl jeweils eine Operation genügt hätte.
Zu Mutexen: Mutex-Freigabe sollte so früh wie möglich erfolgen und nicht erst am Ende des Scopes. Man kann sich natürlich so behelfen:void f() { { Mutex lock; do_something_that_is_not_thread_safe(); } // <-- unlock! do_other_stuff(); do_more_stuff(); }
Aber das ist häßlicher und unituitiver als eine manuelle Freigabe mittels einer simplen Unlock-Funktion.
RAII ist typisch für C++ insgeamt: man erfindet ein, auf den ersten Blick, tolles Feature, baut es sofort in die Sprache ein und schaltet dann sein Gehirn aus.
-
RAII stinkt schrieb:
Zu Mutexen: Mutex-Freigabe sollte so früh wie möglich erfolgen und nicht erst am Ende des Scopes. Man kann sich natürlich so behelfen:
void f() { { Mutex lock; do_something_that_is_not_thread_safe(); } // <-- unlock! do_other_stuff(); do_more_stuff(); }
Aber das ist häßlicher und unituitiver als eine manuelle Freigabe mittels einer simplen Unlock-Funktion.
RAII ist typisch für C++ insgeamt: man erfindet ein, auf den ersten Blick, tolles Feature, baut es sofort in die Sprache ein und schaltet dann sein Gehirn aus.
Ja, man kann sein Hirn ausschalten und es so machen, oder einfach in do_something_that_is_not_thread_safe() locken.
-
Die Java versionen sehen meisten viel besser aus.
File f = null; try{ f = new ... } catch(E...) { } finally { if( f != null ) { try{ f.close() catch(E...) { } } }
-
ja schrieb:
RAII stinkt schrieb:
Zu Mutexen: Mutex-Freigabe sollte so früh wie möglich erfolgen und nicht erst am Ende des Scopes. Man kann sich natürlich so behelfen:
void f() { { Mutex lock; do_something_that_is_not_thread_safe(); } // <-- unlock! do_other_stuff(); do_more_stuff(); }
Aber das ist häßlicher und unituitiver als eine manuelle Freigabe mittels einer simplen Unlock-Funktion.
RAII ist typisch für C++ insgeamt: man erfindet ein, auf den ersten Blick, tolles Feature, baut es sofort in die Sprache ein und schaltet dann sein Gehirn aus.
Ja, man kann sein Hirn ausschalten und es so machen, oder einfach in do_something_that_is_not_thread_safe() locken.
Vorausgesetzt Du hast Zugriff auf die Interna dieser Funktion. Und selbst wenn, was machst Du, wenn ein Lock in do_something_that_is_not_thread_safe() nicht immer erwünscht ist, oder in den Lock von f() noch anderer Code hinein muß? RAII ist keine generelle Lösung für Resource Allocation (was leider immer wieder propagiert wird), sondern ein halbdurchdachte Krücke, die schlechten Code erst möglich macht