Erst C oder gleich C++ ???
-
Tradition wuerde ich tippen. Und weil man gut C++ koennen muss um zu wissen wo die Overheads stecken koennten. Auch die Verfuegbarkeit der Compiler koennte eine Rolle spielen.
-
wieso gibt es delete und delete[]?
aus performance gründen
das verstehe ich nicht. in dem allozierten block ist doch schon die information gespeichert, wie gross er ist. ein zusätzliches delete[] müsste es doch gar nicht geben.
delete[] fuehrt den Destruktor jedes einzelnden Elementes aus.
Das kann erwuenscht sein oder auch nicht - haelst Du fuer ueberfluessig?
-
Shade Of Mine schrieb:
~fricky schrieb:
wenn du schon so fragst: wieso gibt es delete und delete[]?
aus performance gründen
Unfug. Der Allokator muß ohnehin Metainformationen über den Speicherblock unterbringen. Ob da jetzt auch noch eine Array-Dimension mitgespeichert wird, dadurch aber jeder Menge Laufzeitfehler vorgebeugt wird, macht doch nun keinen Unterschied in der Performance?
(@fricky: da zwischen Allokation und Konstruktion unterschieden wird, muß schon zusätzliche Information untergebracht werden. Aber trotzdem: vier Bytes im Tausch gegen eine vermeidbare Fehlerquelle!)Shade Of Mine schrieb:
Warum darf ich keinen werfen. Das würde mich mal interessieren.
Weil es keinen Sinn macht? Weil es unschön ist?
ich will aber einen int werfen als error code. unheimlich praktisch weil ich plötzlich keine allokationen brauche für das objekt.
Du weichst deiner eigenen Frage aus
Sage mir doch: wozu braucht man das?
Für das vermeiden von Allokationen aka Premature Optimization jedenfalls nicht. Du kannst auch ein std::exception-Derivat implementieren, das für what() ein Literal zurückgibt und auf dem Stack alloziert wird. Keinerlei Allokation vonnöten, dafür alle Vorteile der Polymorphie beim Exception-Handling vorhanden.Shade Of Mine schrieb:
es wurde einfach keine restriktionen an die implementierung gegeben.
klar macht es das feature weniger nützlich.
aber weniger nützlich != undurchdacht"This problem is hard. Let's make it an option and the user can decide!"
In obigem Falle mit std::type_info ist es aber so, daß die Features ohne Mehraufwand gewesen wären: niemand hätte VMTs vergrößern müssen, weil das Nötige eh schon drinsteht. Niemand, der die Funktionalität nicht benötigt, hat größere Executables. Nur die RTL-Programmierer haben ein paar zusätzliche Funktionen zu implementieren, die sich im Wesentlichen aus den Bestandteilen der Implementation von dynamic_cast<> zusammensetzen lassen.
Aufgrund des Fehlens solcher Features halte ich std::type_info schlicht für "undurchdacht".Artchi schrieb:
Dann benutze doch einfach eine andere Sprache als C++. Oder wo ist der Haken?
Als Argument kein Stück besser als IYWTPICPPTPICPP
Edit: Typographie und Eile
-
hellihjb schrieb:
delete[] fuehrt den Destruktor jedes einzelnden Elementes aus.
Das kann erwuenscht sein oder auch nicht - haelst Du fuer ueberfluessig?nein, ich frage mich nur, warum delete nicht selbst erkennen kann, ob es für ein einzelobjekt oder ein array von objekten ausgeführt wird.
-
~fricky schrieb:
trotzdem wird C++ in solchen bereichen eher selten verwendet, sondern stattdessen C. warum? aus unwissenheit, traditionsbewusstsein oder aus gutem grund?
Wenn man schon mit C arbeitet braucht es halt gute Gründe auf C++ umzusteigen. Offensichtlich reichen diese nicht immer aus.
-
Achja, ich vergaß:
Shade Of Mine schrieb:
Auch die Sache mit den Default-Kopierkonstruktoren ist mehr als unschön. Barry Kelly hat das, finde ich, recht schön dargelegt.
Der Artikel ist ja mal ziemlicher Käse.
Hoppla, du bist aber schnell mit abwertenden Urteilen bei der Hand
Shade Of Mine schrieb:
Warum genau sind closures in C++ unmöglich?
Sind sie nicht. Aber ohne GC darfst du die Speicherverwaltung selbst übernehmen.
Schau dir als Beispiel die Closures in Delphi 2009 an, die nicht mit GC, sondern mit Referenzzählung implementiert sind (übrigens hauptsächlich von obengenanntem Barry Kelly, der also vielleicht etwas besser als du darüber Bescheid weiß, welche Komplikationen sich dabei ergeben). So richtig funktional und ohne die Beachtung der Speicherverwaltung kann man Closures eigentlich vor allem im Zusammenhang mit Interfaces benutzen - die auch referenzgezählt werden. Referenzzählung ist eine GC-Variante.Shade Of Mine schrieb:
Default CopyCtor ist etwas sehr sinnvolles: es erlaubt nämlich code ersparnis - man muss die großen 3 nur implementieren wenn man sie braucht. das erspart eine menge arbeit bei hilfsklassen wie zB eine list node.
und datenstrukturen aus c sind generell so leichter zu verwenden.
Hast du den Artikel überhaupt gelesen? Es geht doch nicht darum, auf Kopierkonstruktoren zu verzichten.
-
audacia schrieb:
Shade Of Mine schrieb:
Warum genau sind closures in C++ unmöglich?
Sind sie nicht. Aber ohne GC darfst du die Speicherverwaltung selbst übernehmen.
Schau dir als Beispiel die Closures in Delphi 2009 an, die nicht mit GC, sondern mit Referenzzählung implementiert sind (übrigens hauptsächlich von obengenanntem Barry Kelly, der also vielleicht etwas besser als du darüber Bescheid weiß, welche Komplikationen sich dabei ergeben). So richtig funktional und ohne die Beachtung der Speicherverwaltung kann man Closures eigentlich vor allem im Zusammenhang mit Interfaces benutzen - die auch referenzgezählt werden. Referenzzählung ist eine GC-Variante.Ich kenne nur die closures in c++ und die haben eigentlich kein ref counting dabei...
Hast du den Artikel überhaupt gelesen? Es geht doch nicht darum, auf Kopierkonstruktoren zu verzichten.
Sicher, aber ich dachte dir geht es um default cctors...
der artikel ist doof - sag einfach was du daraus meinst. mag nicht den ganzen artikel zerpflücken müssen.
@~fricky:
nein, es muss nicht gespeichert werden wie groß der bereich ist. meistens wird es dass, aber es wäre mögich es auch ohne zu implementieren.aber selbst wenn es gespeichert wird: delete[] speichert noch mit wie viele objekte hier liegen. das ist eine zusatz information die delete nicht braucht -> du sparst performance
-
Tim schrieb:
~fricky schrieb:
trotzdem wird C++ in solchen bereichen eher selten verwendet, sondern stattdessen C. warum? aus unwissenheit, traditionsbewusstsein oder aus gutem grund?
Wenn man schon mit C arbeitet braucht es halt gute Gründe auf C++ umzusteigen. Offensichtlich reichen diese nicht immer aus.
oder man ist sich der gefahren bewusst. tatsächlich hab' ich mehr als einmal erlebt, dass jemand, durch den (blauäugigen) einsatz von c++ in einem embedded system, fürchterlich auf die nase gefallen ist.
Shade Of Mine schrieb:
@~fricky:
nein, es muss nicht gespeichert werden wie groß der bereich ist. meistens wird es dass, aber es wäre mögich es auch ohne zu implementieren.wie das? delete muss doch wissen, ob es sich um einen einzelnen 'char', oder ein objekt mit 99 members handelt, um die richtige speichermenge wieder freizugeben.
Shade Of Mine schrieb:
delete[] speichert noch mit wie viele objekte hier liegen. das ist eine zusatz information die delete nicht braucht -> du sparst performance
ja, ein lesezugriff und eine bedingte verzweigung, vielleicht 10...20 taktzyklen oder so. die ersparniss ist minimal, dafür hätte man aber eine üble fehlerquelle ausgeschaltet, nämlich das vertauschen von delete[] mit delete.
-
dfgdfgdfg schrieb:
asc schrieb:
C++ : [...] Bietet zusätzlich die Möglichkeiten der generischen Programmierung (bei gleichzeitiger Typsicherheit) und der direkten Unterstützung von OO-Konzepten.
cu André
Wow! Applaus! Soll jetzt jeder Luftsprünge machen?
Das was du da tolles für C++ vorstellst, ist das selbstverstöndlichste auf der welt.Interessanterweise ist die generische Programmierung in den "Mainstream"-Sprachen erst mit C++ wirklich eingekehrt. Als selbstverständlich würde ich das also nicht nennen (Generics & Co in Sprachen wie Java/C# kamen erst danach)
dfgdfgdfg schrieb:
C++ ruht sich auf Lohrbeeren aus, die schon seit ~30 jahren als etwas selbstverstäünliches in highlevelsprachen sind.
So? Ich wusste noch gar nicht das Templates in C++ 30 Jahre alt sind (Den darauf beziehe ich mich u.a.). Dir ist hoffentlich bewusst das die Sprache C++ im Wandel ist, C++98, TR1 (C++03), C++09 seien hier nur genannt.
-
~fricky schrieb:
...sabbel...
Ist klar, weil einem so wenig unsichere Konstrukte in C++ einfallen, muss eben delete herhalten.
Mir fallen da jede Menge Dinge in C ein, die unsicher sind. Das fängt schon beim printf/scanf an, geht über das gesamte Bastelei mit Strings und Arrays bis hin zu so tollen Sachen wie die wenigen Standardalgorithmen die absolut 0 Typsicherheit bieten.
Man muss eben wissen, was man tut. Das gilt, wer hätte das gedacht, auch für C++, Ada und alle möglichen anderen Sprachen.
In C braucht es Disziplin um was Ordentliches zu Stande zu bringen. In C++ muss man sich von alten Strukturen lösen und auf C++-Konstrukte umsatteln. Das fällt Anachronisten (und C++ ist heute nicht mehr das, was es war als es besagte Anachronisten offensichtlich ausprobiert haben) oft schwer, und deshalb kommt oft Schrott dabei raus.
Ich weiß nicht wie andere Leute C++ programmieren (bei fricky habe ich allerdings so eine grobe Vorstellung), aber bei mir deckt der Compiler bereits die meisten Fehler auf. Die Fehler die noch da sind, sind meist eher Logikfehler. Und die hätte man in jeder Sprache.Um auf die Frage des TOs zurückzukommen:
Wenn es um die Wahl zwischen C und C++ geht und sonst keine Sprachen in Frage kommen, würde ich mit C++ beginnen, und mir auch ein richtiges C++-Buch dazu kaufen (und keines das mit C in Klassen, C++ mit Visual Studio oder sonstigem Quark beginnt). Dann ist C++ auch einfacher als C.
-
~fricky schrieb:
dafür hätte man aber eine üble fehlerquelle ausgeschaltet, nämlich das vertauschen von delete[] mit delete.
ist das wirklich ein fehler der oft vorkommt?
bei anfängern vielleicht, aber ich hab das eigentlich noch nie in einem produktiv code gesehen.
-
~fricky schrieb:
trotzdem wird C++ in solchen bereichen eher selten verwendet, sondern stattdessen C. warum? aus unwissenheit, traditionsbewusstsein oder aus gutem grund?
Keine Ahnung. Ich weiß zwar das C z.B. im Embedded-Bereich häufig ist, aber die eizigen Bekannten in dieser Branche die ich kenne arbeiten Tatsächlich mit C++.
Ich würde sagen es verhält sich hier wie mit jeder anderen Sprache: Es hält sich zum Teil aus Tradition. Die wenigsten Firmen wechseln sofort - oder wenn das Wissen fehlt auch garnicht.
Das ist so wie mit den C++ Feature ab dem C++ Standard: Ich kenne viele Firmen die bis heute nicht die STL einsetzen, und zwar nicht wegen Overhead etc (das ist im Embedded-Bereich ein Thema, die meisten Firmen mit denen ich Kontakt habe sind in anderen Branchen tätig), sondern aus reiner Unwissenheit und Sturheit der Alten.
Mich stört nicht das man nicht jeden Trend mitmacht, mich stört auch nicht das C existiert, obwohl ich persönlich dann schon C++ vorziehe - da soll jede Firma selbst entscheiden. Was mich in der Praxis aber wirklich stört ist, das die Älteren häufig sich gegen jegliche Neuerung querstellen, und damit auch jeden Fortschritt behindern. Nicht jede Neuerung ist gut, aber wenn es dazu führt das z.B. Firmen noch Entwicklungsumgebungen einsetzen deren Support schon Anno Dazumal eingestellt wurden ist, die alles Wissen das Neue mitbringen bereits im Keim ersticken (Nein, du machst das wie ich) - dann sollen sie sich nicht wundern wenn irgendwann ihr ach so tolles (und kaum wartbares) Stück Software nicht mehr auf neuen Betriebssystemen läuft, und die Kunden abspringen.
cu André
-
Shade Of Mine schrieb:
~fricky schrieb:
dafür hätte man aber eine üble fehlerquelle ausgeschaltet, nämlich das vertauschen von delete[] mit delete.
ist das wirklich ein fehler der oft vorkommt?
bei anfängern vielleicht, aber ich hab das eigentlich noch nie in einem produktiv code gesehen.Mhh, also ich sehe häufig gar kein delete im Produktivcode mehr (Eher ein boost::scoped_ptr und ähnliches ;p). Okay, in der Regel nachdem ich an dem Code gearbeitet habe...
cu André
-
Tachyon schrieb:
Ist klar, weil einem so wenig unsichere Konstrukte in C++ einfallen, muss eben delete herhalten.
wenn dir das thema nicht gefällt, können wir uns auch gern darüber unterhalten, warum man von stl-klassen zwar ableiten kann, aber es nicht sollte. oder wie man einer funktion ansieht, ob konstruktor-tauglich ist (weil sie exceptions wirft oder nicht). vielleicht wäre die frage, warum cout << x^1 + 1; nicht funzt, printf ("%d\n", x^1 + 1); aber schon, angenehmer für dich?
Shade Of Mine schrieb:
~fricky schrieb:
dafür hätte man aber eine üble fehlerquelle ausgeschaltet, nämlich das vertauschen von delete[] mit delete.
ist das wirklich ein fehler der oft vorkommt?
er wird wahrscheinlich ähnlich häufig vorkommen, wie das vergessen von delete. ich glaube, noch nicht mal der compiler erkennt den fehler.
-
~fricky schrieb:
...
Ist klar, Du greifst Dir den Teil der offensichtlich pire Ironie war, und gehst auf die ernst gemeinten Aussagen nicht ein.
-
namespace invader schrieb:
Irgendwie gibt es für alles besser geeignete Sprachen als C++
ich wäre spontan geneigt, zuzustimmen
, allerdings bin ich der Meinung, daß für
resourcenkritische Projekte von nicht ganz trivialer Größenordnung, sagen wir mal, ab 10000-20000 Zeilen, C++ eine gute Wahl ist, vor allem, wenn wichtig ist, daß sich die Sprache nicht so schnell ändert, damit der Code auch noch in 10 Jahren ohne allzu viele Änderungen compiliert.
-
~fricky schrieb:
Tachyon schrieb:
Ist klar, weil einem so wenig unsichere Konstrukte in C++ einfallen, muss eben delete herhalten.
wenn dir das thema nicht gefällt, können wir uns auch gern darüber unterhalten, warum man von stl-klassen zwar ableiten kann, aber es nicht sollte. oder wie man einer funktion ansieht, ob konstruktor-tauglich ist (weil sie exceptions wirft oder nicht). vielleicht wäre die frage, warum cout << x^1 + 1; nicht funzt, printf ("%d\n", x^1 + 1); aber schon, angenehmer für dich?
Shade Of Mine schrieb:
~fricky schrieb:
dafür hätte man aber eine üble fehlerquelle ausgeschaltet, nämlich das vertauschen von delete[] mit delete.
ist das wirklich ein fehler der oft vorkommt?
er wird wahrscheinlich ähnlich häufig vorkommen, wie das vergessen von delete. ich glaube, noch nicht mal der compiler erkennt den fehler.
Eigentlich gar nie, denn new normal muss man kein delete zum new dazu schreiben, da das ungefähr so aussieht:
if (blablubb) { boost::scoped_ptr< my_class >( new my_class ); }
Wohl gemerkt: eine Klasse sollte genau eine (wohl-)definierte Aufgabe übernehmen.
Sollte man innerhalb einer Klasse einmal unartig sein und einen nakten Zeiger auf ein Heap-Objekt verwalten, so ist es wirklich kein Akt ein delete in den Destruktor zu schreiben.
Es ist ungfähr so schwierig wie das Schuhe binden nach dem Schuhe anziehen.
-
~~fricky schrieb:
~fricky schrieb:
Tachyon schrieb:
Ist klar, weil einem so wenig unsichere Konstrukte in C++ einfallen, muss eben delete herhalten.
wenn dir das thema nicht gefällt, können wir uns auch gern darüber unterhalten, warum man von stl-klassen zwar ableiten kann, aber es nicht sollte. oder wie man einer funktion ansieht, ob konstruktor-tauglich ist (weil sie exceptions wirft oder nicht). vielleicht wäre die frage, warum cout << x^1 + 1; nicht funzt, printf ("%d\n", x^1 + 1); aber schon, angenehmer für dich?
Shade Of Mine schrieb:
~fricky schrieb:
dafür hätte man aber eine üble fehlerquelle ausgeschaltet, nämlich das vertauschen von delete[] mit delete.
ist das wirklich ein fehler der oft vorkommt?
er wird wahrscheinlich ähnlich häufig vorkommen, wie das vergessen von delete. ich glaube, noch nicht mal der compiler erkennt den fehler.
Eigentlich gar nie, denn new normal muss man kein delete zum new dazu schreiben, da das ungefähr so aussieht:
if (blablubb) { boost::scoped_ptr< my_class >( new my_class ); }
Wohl gemerkt: eine Klasse sollte genau eine (wohl-)definierte Aufgabe übernehmen.
Sollte man innerhalb einer Klasse einmal unartig sein und einen nakten Zeiger auf ein Heap-Objekt verwalten, so ist es wirklich kein Akt ein delete in den Destruktor zu schreiben.
Es ist ungfähr so schwierig wie das Schuhe binden nach dem Schuhe anziehen.Hehe, ich schätze mal ~fricky läuft öfter mal mit roten Knien herum
-
~~fricky schrieb:
Sollte man innerhalb einer Klasse einmal unartig sein und einen nakten Zeiger auf ein Heap-Objekt verwalten, so ist es wirklich kein Akt ein delete in den Destruktor zu schreiben.
Es ist ungfähr so schwierig wie das Schuhe binden nach dem Schuhe anziehen.Aber nicht den Kopierkonstruktor und den Zuweisungsoperator vergessen.
-
Shade Of Mine schrieb:
Ich kenne nur die closures in c++ und die haben eigentlich kein ref counting dabei...
Dafür aber manuelles Speichermanagement. Natürlich kann man sich das mit Smart-Pointern o.ä. vereinfachen - aber das ist auch wieder eine GC-Variante.
Oder falls du __closure in C++Builder meinst: das ist eine retrospektiv als unglücklich einzuschätzende Wortwahl, hat aber mit den anonymen Methoden von Delphi 2009, besser bekannt als Closures, nicht das Geringste zu tun.
Shade Of Mine schrieb:
Sicher, aber ich dachte dir geht es um default cctors...
Was auch immer. Das komplette "Jedes struct ist jetzt eine Klasse" inklusive aller Implikationen, eine davon z.B. Default-, Kopierkonstruktor und Zuweisungsoperator für alle Klassen, ist ein gewaltiger Designfehler - IMHO.
Shade Of Mine schrieb:
der artikel ist doof
Du bist unqualifiziert.
Shade Of Mine schrieb:
sag einfach was du daraus meinst. mag nicht den ganzen artikel zerpflücken müssen.
Brauchst du gar nicht. Er ist eigentlich, von der Einleitung abgesehen, recht fixiert auf das Thema, das ich ansprach. Wieso soll ich das jetzt nochmal erklären?
Shade Of Mine schrieb:
das ist eine zusatz information die delete nicht braucht -> du sparst performance
Abstrus.
Der tatsächliche Grund dürfte sein, daß new[] erst nach new eingeführt wurde und man vermutlich irgendein ABI nicht kaputtmachen wollte.