Ich habe kürzlich D gelernt und fange an, mich mit der Sprache vertraut zu machen. Ich weiß, was es bietet, ich weiß noch nicht, wie man alles benutzt, und ich weiß nicht viel über D-Redewendungen und so weiter, aber ich lerne.
Ich mag D. Es ist eine nette Sprache, die in gewisser Weise ein großes Update für C ist und gut gemacht wird. Keines der Features scheint "angeschraubt" zu sein, aber eigentlich recht durchdacht und durchdacht.
Sie werden oft hören, dass D das ist, was C ++ hätte sein sollen (ich überlasse die Frage, ob dies für jeden zutreffend ist, um unnötige Flammenkriege zu vermeiden). Ich habe auch von mehreren C ++ - Programmierern gehört, dass sie D viel mehr mögen als C ++.
Obwohl ich C kenne, kann ich nicht sagen, dass ich C ++ kenne. Ich möchte von jemandem hören , sowohl C zu wissen ++ und D , wenn sie denken , dass es etwas ist , das C ++ funktioniert besser als D als Sprache (was bedeutet , nicht die üblichen „es Bibliotheken von Drittanbietern hat“ oder „es gibt mehr Ressourcen“ oder " es gibt mehr Jobs, die C ++ erfordern als D ").
D wurde von einigen sehr erfahrenen C ++ - Programmierern ( Walter Bright und Andrei Alexandrescu , mit Hilfe der D-Community) entwickelt, um viele der Probleme, die C ++ hatte, zu beheben. Gab es jedoch etwas, das eigentlich nicht besser wurde? Etwas, das er verpasst hat? Etwas, von dem Sie denken, dass es keine bessere Lösung ist?
Beachten Sie auch, dass ich von D 2.0 spreche , nicht von D 1.0 .
quelle
Antworten:
Die meisten Dinge, die C ++ besser macht als D, sind Meta-Dinge: C ++ hat bessere Compiler, bessere Tools, ausgereiftere Bibliotheken, mehr Bindungen, mehr Experten, mehr Tutorials usw. Grundsätzlich hat es mehr und besser von allen externen Dingen, die Sie haben würde von einer reiferen Sprache erwarten. Das ist unbestreitbar.
Was die Sprache selbst betrifft, gibt es meiner Meinung nach ein paar Dinge, die C ++ besser kann als D. Es gibt wahrscheinlich mehr, aber hier sind ein paar, die ich ganz oben auflisten kann:
C ++ hat ein besser durchdachtes Typensystem
Im Moment gibt es einige Probleme mit dem Typensystem in D, die anscheinend zu übersehen sind. Zum Beispiel ist es derzeit nicht möglich, eine const-Struktur in eine Nicht-const-Struktur zu kopieren, wenn die Struktur Klassenobjektreferenzen oder -zeiger enthält, da const transitiv ist und Postblit-Konstruktoren mit Werttypen arbeiten. Andrei sagt, er weiß, wie man das löst, hat aber keine Details angegeben. Das Problem ist sicherlich behebbar (die Einführung von C ++ - Kopierkonstruktoren wäre eine Lösung), aber es ist derzeit ein großes sprachliches Problem.
Ein weiteres Problem, das mich gestört hat, ist das Fehlen von logischen Konstanten (dh nicht
mutable
wie in C ++). Dies ist großartig, um thread-sicheren Code zu schreiben, macht es jedoch schwierig (unmöglich?), Eine verzögerte Initialisierung innerhalb von const-Objekten durchzuführen (denken Sie an eine const-Funktion 'get', die den zurückgegebenen Wert beim ersten Aufruf erstellt und zwischenspeichert).Schließlich, da diese bestehenden Probleme, ich mache mir Sorgen darüber , wie der Rest des Typs System (
pure
,shared
usw.) mit allem anderen in der Sprache zu interagieren , wenn sie in Gebrauch genommen. Die Standardbibliothek (Phobos) nutzt das fortschrittliche Typensystem von D derzeit nur sehr wenig, daher halte ich es für vernünftig, die Frage zu klären, ob es unter Stress bestehen bleibt. Ich bin skeptisch, aber optimistisch.Beachten Sie, dass C ++ einige Warzen im Typsystem hat (z. B. nicht-transitives const, erfordert
iterator
sowieconst_iterator
), die es ziemlich hässlich machen, aber während das Typsystem von C ++ in Teilen ein wenig falsch ist, hindert es Sie nicht daran, die Arbeit wie das von D zu erledigen manchmal schon.Edit: Um das zu verdeutlichen, glaube ich, dass C ++ ein besser durchdachtes Typsystem hat - nicht unbedingt ein besseres - wenn das Sinn macht. Grundsätzlich besteht in DI das Risiko, dass alle Aspekte des Typsystems verwendet werden, die in C ++ nicht vorhanden sind.
D ist manchmal etwas zu bequem
Ein Kritikpunkt, den Sie oft von C ++ hören, ist, dass es einige Probleme auf niedriger Ebene vor Ihnen verbirgt, z. B. einfache Zuweisungen
a = b;
, die viele Dinge wie das Aufrufen von Konvertierungsoperatoren, das Aufrufen von Überladungszuweisungsoperatoren usw. erledigen können schwer aus dem Code zu sehen. Manche mögen das, manche nicht. So oder so, in D ist es schlechter (besser?) Aufgrund Dinge wieopDispatch
,@property
,opApply
, ,lazy
die das Potenzial haben , unschuldig aussehenden Code in den Dinge zu ändern , die Sie nicht erwarten.Ich glaube nicht, dass dies persönlich ein großes Problem ist, aber manche mögen dies als abstoßend empfinden.
D erfordert Garbage Collection
Dies kann als umstritten angesehen werden, da D ohne GC ausgeführt werden kann. Nur weil es möglich ist, heißt das noch lange nicht, dass es praktisch ist. Ohne einen GC verlieren Sie viele Funktionen von D, und die Verwendung der Standardbibliothek ist wie ein Spaziergang durch ein Minenfeld (wer weiß, welche Funktionen Speicher zuweisen?). Persönlich halte ich es für völlig unpraktisch, D ohne GC zu verwenden, und wenn Sie kein GC-Fan sind (wie ich), kann dies ziemlich abstoßend sein.
Naive Array-Definitionen in D
belegen Speicher
Um die Zuordnung in D zu vermeiden, müssen Sie anscheinend Folgendes tun:
Diese kleinen Zuweisungen hinter deinem Rücken sind gute Beispiele für meine beiden vorherigen Punkte.
Bearbeiten: Beachten Sie, dass dies ein bekanntes Problem ist, an dem gerade gearbeitet wird.Bearbeiten: Dies ist jetzt behoben. Es findet keine Zuordnung statt.
Fazit
Ich habe mich auf die Negative von D vs C ++ konzentriert, da dies die gestellte Frage ist, aber bitte sehen Sie diesen Beitrag nicht als Aussage, dass C ++ besser ist als D. Ich könnte leicht einen größeren Beitrag von Stellen machen, an denen D besser ist als C ++. Es liegt an Ihnen, die Entscheidung zu treffen, welche Sie verwenden möchten.
quelle
Als ich zu D development kam, war ich in der besonderen Position, einer der Leute zu sein, die am meisten über C ++ wissen. Jetzt bin ich in der noch eigentümlicheren Position, auch einer der Menschen zu sein, die am besten wissen, dass es etwas über D gibt vorteilhafte Position zur Beantwortung dieser Frage. Gleiches gilt für Walter.
Im Großen und Ganzen ist die Frage, was C ++ (und damit meine ich C ++ 2011) besser macht als D, ebenso widersprüchlich wie die Frage: "Wenn Sie einen Fachmann für die Reinigung Ihres Hauses bezahlen, welche Orte werden sie verlassen? dreckiger als vorher? " Was auch immer von Wert war, dass C ++ das tun konnte, was D nicht konnte, es war für mich und Walter immer wie ein wunder Daumen, also gibt es fast per Definition nichts, was C ++ jemals tun kann, was nicht in Ds Reichweite ist.
Eine Sache, die im Sprachdesign selten verstanden wird (weil nur wenige Menschen das Glück haben, tatsächlich etwas zu tun), ist, dass es viel weniger ungezwungene Fehler gibt, als es erscheinen mag. Viele von uns Sprachbenutzern schauen sich das eine oder andere Konstrukt an und sagen: "Ew! Das ist so falsch! Was dachten sie?" Tatsache ist, dass die meisten unangenehmen Fälle in einer Sprache auf einige grundlegende Entscheidungen zurückzuführen sind, die alle stichhaltig und wünschenswert sind, sich jedoch grundlegend widersprechen oder widersprechen (z. B. Modularität und Effizienz, Knappheit und Kontrolle usw.).
Vor diesem Hintergrund werde ich ein paar Dinge aufzählen, die mir einfallen, und für jede erläutere ich, wie Ds Entscheidung aus dem Wunsch resultiert, eine andere Charta auf höherer Ebene zu erfüllen.
D setzt voraus, dass alle Objekte bitweise kopiert werden können. Dies überlässt C ++ eine Minderheit von Designs, insbesondere solchen, die interne Zeiger verwenden, dh eine Klasse, die Zeiger in sich enthält. (Ein solches Design kann ohne oder mit zu vernachlässigenden Kosten für die Effizienz in D übersetzt werden, es wäre jedoch ein Übersetzungsaufwand erforderlich.) Wir haben diese Entscheidung getroffen, um die Sprache erheblich zu vereinfachen, das Kopieren von Objekten effizienter zu gestalten, ohne oder mit minimalem Benutzereingriff, und zu vermeiden Der gesamte Kopierkonstruktions-Morast und die R-Wert-Referenzen sind insgesamt vorhanden.
D verbietet Typen mit mehrdeutigem Geschlecht (die nicht entscheiden können, ob es sich um Werttypen oder Referenztypen handelt). Solche Designs werden in C ++ einhellig gemieden und sind fast immer falsch, aber einige davon sind technisch korrekt. Wir haben diese Wahl getroffen, weil sie meistens falschen Code und nur einen winzigen Bruchteil korrekten Code verbietet, der neu gestaltet werden kann. Wir glauben, dass es ein guter Kompromiss ist.
D erlaubt keine Hierarchien mit mehreren Wurzeln. Ein früheres Poster hier hat sich sehr über dieses spezielle Thema gefreut, aber das ist ausgetreten und es gibt keinen spürbaren Vorteil von Hierarchien ohne Wurzel gegenüber Hierarchien, die alle eine gemeinsame Wurzel haben.
In D kann man zB kein int werfen. Sie müssen ein Objekt werfen, das Throwable erbt. Kein Wettbewerb, bei dem der Stand der Dinge in D besser ist, aber es ist eine Sache, die C ++ kann, die D nicht kann.
In C ++ ist die Kapselungseinheit eine Klasse. In D ist es ein Modul (dh eine Datei). Walter traf diese Entscheidung aus zwei Gründen: Um die Kapselung auf natürliche Weise der Dateisystemschutzsemantik zuzuordnen und die Notwendigkeit eines "Freundes" zu vermeiden. Diese Wahl fügt sich sehr gut in das modulare Gesamtdesign von D ein. Es wäre möglich, Dinge so zu ändern, dass sie eher C ++ ähneln, aber das würde die Dinge zwingen. Die Auswahlmöglichkeiten für den Kapselungsbereich von C ++ sind nur für das physische Design von C ++ von Vorteil.
Es könnte ein oder zwei kleinere Dinge geben, aber insgesamt sollte es so sein.
quelle
Object*
so häufig verwendet werden wie einint*
?), Und D scheint dies völlig zu ignorieren die Leistungsstrafe, oder behaupten, dass es nicht existiert. Das ist offensichtlich falsch - der Cache-Fehler ist in vielen Fällen ziemlich auffällig, so dass C ++ immer diesen Flexibilitätsvorteil gegenüber D hat.Ich denke, es wird Ihnen sehr schwer fallen, in D viel zu finden, was objektiv istschlimmer als C ++. Die meisten Probleme mit D, von denen man objektiv sagen könnte, dass sie schlechter sind, sind entweder Probleme mit der Qualität der Implementierung (die im Allgemeinen darauf zurückzuführen sind, wie jung die Sprache und die Implementierung sind und in letzter Zeit mit rasender Geschwindigkeit behoben wurden) oder sie sind Probleme mit einem Mangel an Bibliotheken von Drittanbietern (die mit der Zeit kommen werden). Die Sprache selbst ist im Allgemeinen besser als C ++, und die Fälle, in denen C ++ als Sprache besser ist, sind im Allgemeinen entweder dort, wo es einen Kompromiss gibt, wo C ++ in eine Richtung und D in eine andere Richtung ging, oder wo jemand subjektive Gründe dafür hat denke, dass einer besser ist als der andere. Die Anzahl der ausgesprochen objektiven Gründe, warum C ++ als Sprache besser ist, dürfte jedoch gering sein.
Tatsächlich muss ich mein Gehirn wirklich aus dem Konzept bringen, warum C ++ als Sprache besser ist als D. Was mir im Allgemeinen einfällt, ist eine Frage der Kompromisse.
Da Ds const transitiv ist und die Sprache unveränderlich ist , hat sie weitaus stärkere Garantien als C ++
const
, was bedeutet, dass D keine hat und nicht haben kannmutable
. Es kann keine logische const haben . Mit dem const-System von D erhalten Sie also einen enormen Gewinn, aber in manchen Situationen können Sie es einfach nicht so verwenden,const
wie Sie es in C ++ getan hätten.D hat nur einen Umsetzungsoperator, während C ++ 4 hat (5, wenn Sie den C-Umsetzungsoperator zählen). Dies erleichtert im Allgemeinen den Umgang mit Darstellungen in D, ist jedoch problematisch, wenn Sie tatsächlich die zusätzlichen Komplikationen / Vorteile möchten, die diese
const_cast
und ihre Brüder bieten. Aber D ist tatsächlich leistungsfähig genug, dass Sie Templates verwenden können, um C ++ - Casts zu implementieren. Wenn Sie sie also wirklich wollen, können Sie sie haben (und sie können sogar irgendwann in der Standardbibliothek von D landen).D hat weitaus weniger implizite Casts als C ++ und deklariert mit weitaus höherer Wahrscheinlichkeit, dass zwei Funktionen miteinander in Konflikt stehen (was Sie dazu zwingt, genauer zu bestimmen, welche der Funktionen Sie meinen - entweder mit Casts oder durch Angabe des vollständigen Modulpfads ). Manchmal kann das ärgerlich sein, aber es verhindert alle Arten von Problemen bei der Funktionsentführung . Sie wissen, dass Sie wirklich die Funktion aufrufen, die Sie wollen.
Ds Modulsystem ist weitaus sauberer als das #includes von C ++ (ganz zu schweigen davon, dass es beim Kompilieren viel schneller ist), aber es fehlen jegliche Namensräume, die über die Module selbst hinausgehen. Wenn Sie also einen Namespace innerhalb eines Moduls benötigen, müssen Sie die Java-Route einschlagen und statische Funktionen für eine Klasse oder Struktur verwenden. Es funktioniert, aber wenn Sie wirklich Namespaces benötigen, ist es offensichtlich nicht so sauber wie echte Namespaces. In den meisten Situationen ist der Namespace, den die Module selbst zur Verfügung stellen, jedoch ausreichend (und ziemlich ausgefeilt, wenn es um Dinge wie Konflikte geht).
Wie Java und C # hat D eine einfache Vererbung und keine mehrfache Vererbung. Im Gegensatz zu Java und C # bietet es jedoch einige fantastische Möglichkeiten, den gleichen Effekt zu erzielen, ohne dass alle Probleme auftreten, die die mehrfache Vererbung von C ++ mit sich bringt (und die mehrfache Vererbung von C ++ kann sehr chaotisch werden) manchmal). D hat nicht nur Schnittstellen , sondern auch String-Mixins , Template-Mixins und diesen Alias . Das Endergebnis ist also wahrscheinlich leistungsfähiger und weist nicht alle Probleme auf, die die Mehrfachvererbung von C ++ verursacht.
Ähnlich wie in C # trennt D Strukturen und Klassen . Klassen sind Referenztypen
Object
, die vererbt und abgeleitet sind , während Strukturen Werttypen ohne Vererbung sind. Diese Trennung kann sowohl gut als auch schlecht sein. Es beseitigt das klassische Slicing-Problem in C ++ und hilft dabei, Typen, die wirklich Werttypen sind, von solchen zu trennen, die polymorph sein sollen, aber zumindest könnte die Unterscheidung für einen C ++ - Programmierer zunächst ärgerlich sein. Letztendlich hat es eine Reihe von Vorteilen, aber es zwingt Sie dazu, etwas anders mit Ihren Typen umzugehen.Member - Funktionen von Klassen sind polymorph standardmäßig. Sie können sie nicht als nicht virtuell deklarieren . Es ist Sache des Compilers, zu entscheiden, ob dies möglich ist (was wirklich nur der Fall ist, wenn sie final sind und eine Funktion einer Basisklasse nicht überschreiben). Das könnte also in einigen Fällen ein Leistungsproblem sein. Wenn Sie den Polymorphismus jedoch wirklich nicht benötigen, müssen Sie nur Strukturen verwenden , und das ist kein Problem.
D hat eine eingebaute Müllabfuhr . Viele von C ++ würden dies als ernstzunehmenden Nachteil betrachten, und um ehrlich zu sein, könnte die Implementierung derzeit einige ernstzunehmende Arbeiten erfordern. Es hat sich verbessert, aber es ist definitiv noch nicht auf dem Niveau von Javas Müllsammler. Dies wird jedoch durch zwei Faktoren gemildert. Erstens , wenn Sie hauptsächlich Strukturen und andere Datentypen auf dem Stack verwenden, ist dies kein großes Problem. Wenn Ihr Programm nicht ständig Dinge auf dem Heap zuordnet und freigibt, ist dies in Ordnung. Und zweitens können Sie den Garbage Collector überspringen , wenn Sie möchten, und einfach Cs
malloc
und verwendenfree
. Es gibt einige Sprachfunktionen (z. B. Array-Slicing)), die Sie vermeiden oder mit denen Sie vorsichtig sein müssen, und einige der Standardbibliotheken sind ohne die Verwendung des GC (insbesondere der Zeichenfolgenverarbeitung) nicht wirklich verwendbar , aber Sie können in D schreiben, ohne den Garbage Collector zu verwenden, wenn du willst es wirklich. Das Schlaue ist wahrscheinlich, es im Allgemeinen zu verwenden und dann zu vermeiden, wenn die Profilerstellung zeigt, dass es Probleme für leistungskritischen Code verursacht. Sie können es jedoch vollständig vermeiden, wenn Sie möchten. Und die Qualität der GC -Implementierung wird sich mit der Zeit verbessern, wodurch viele der Bedenken beseitigt werden, die die Verwendung eines GC verursachen kann. Letztendlich ist der GC also kein so großes Problem, und im Gegensatz zu Java können Sie ihn vermeiden, wenn Sie möchten.Es gibt wahrscheinlich auch andere, aber genau das kann ich mir gerade einfallen lassen. Und wenn Sie bemerken, sind sie alle Kompromisse. D entschied sich dafür, einige Dinge anders zu machen als C ++, die eindeutige Vorteile gegenüber C ++ haben, aber auch einige Nachteile. Was besser ist, hängt davon ab, was Sie tun. In vielen Fällen wird es wahrscheinlich erst schlimmer erscheinen, und wenn Sie sich daran gewöhnt haben, werden Sie kein Problem damit haben. Wenn überhaupt, werden die Probleme in D im Allgemeinen neue sein, die durch neue Dinge verursacht werden, die andere Sprachen vorher nicht oder nicht ganz so gemacht haben wie D. Insgesamt hat D sehr gut aus den Fehlern von C ++ gelernt.
Und D als Sprache verbessert C ++ in so vielen Punkten, dass ich denke, dass es im Allgemeinen der Fall ist, dass D objektiv besser ist.
D hat bedingte Kompilierung . Dies ist eine der Funktionen, die ich beim Programmieren in C ++ häufig vermisse. Wenn C ++ es hinzufügen würde, würde sich C ++ sprunghaft verbessern, wenn es um Dinge wie Vorlagen geht.
D hat eine Kompilierzeitreflexion .
Variablen sind standardmäßig thread-lokal, können es aber auch sein,
shared
wenn Sie dies möchten. Dies macht den Umgang mit Threads weitaus sauberer als in C ++. Sie haben die volle Kontrolle. Sie verwenden können ,immutable
und Message - Passing zwischen Threads zu kommunizieren, oder Sie können Variablen machenshared
und tun es die C ++ Art und Weise mit Mutexe und Bedingungsvariablen. Selbst das wird gegenüber C ++ durch die Einführung von Synchronized (ähnlich wie C # und Java) verbessert . Die Threading-Situation von D ist also weitaus besser als die von C ++.Die Vorlagen von D sind weitaus leistungsfähiger als die von C ++, sodass Sie weitaus mehr und einfacher tun können. Und mit der Zugabe von Template - Einschränkungen sind die Fehlermeldungen Art und Weise besser , als sie in C ++. D macht Vorlagen sehr leistungsfähig und benutzerfreundlich. Es ist kein Zufall, dass der Autor von Modern C ++ Design einer der Hauptmitarbeiter von D ist. Ich finde, dass C ++ - Vorlagen im Vergleich zu D-Vorlagen ernsthaft fehlen, und es kann manchmal sehr frustrierend sein, wenn in C ++ programmiert wird.
D verfügt über eine integrierte Vertragsprogrammierung .
D verfügt über ein integriertes Unit-Test- Framework.
D unterstützt Unicode mit
string
(UTF-8),wstring
(UTF-16) unddstring
(UTF-32). Es macht es einfach, mit Unicode umzugehen. Und wenn Sie nurstring
Unicode verwenden möchten und sich im Allgemeinen nicht um Unicode kümmern möchten , können Sie dies. Ein gewisses Verständnis der Grundlagen von Unicode hilft jedoch bei einigen der Standardfunktionen der Bibliothek.Das Überladen von Operatoren in D ist viel angenehmer als in C ++, sodass Sie mit einer Funktion mehrere Operatoren gleichzeitig überladen können. Ein hervorragendes Beispiel hierfür ist, wenn Sie die grundlegenden arithmetischen Operatoren überladen müssen und ihre Implementierungen bis auf den Operator identisch sind. String-Mixins machen es zu einem Kinderspiel und ermöglichen Ihnen eine einfache Funktionsdefinition für alle.
Die Arrays von D sind weitaus besser als die von C ++. Sie sind nicht nur ein richtiger Typ mit einer Länge, sondern können auch angehängt und in der Größe geändert werden. Sie zu verketten ist einfach. Und das Beste ist, dass sie in Scheiben schneiden . Und das ist ein großer Segen für eine effiziente Array-Verarbeitung. Strings sind Arrays von Zeichen in D, und es ist kein Problem (in der Tat ist es großartig!), Weil Ds Arrays so mächtig sind.
Ich könnte weiter und weiter gehen. Viele der Verbesserungen, die D bietet, sind Kleinigkeiten (wie die Verwendung
this
für Konstruktornamen oder das Nichtzulassen von Anweisungen oder Schleifenkörpern, bei denen ein Semikolon der gesamte Körper ist), aber einige von ihnen sind ziemlich groß, und wenn Sie alles zusammenfassen, ist es sorgt für ein viel besseres Programmiererlebnis. C ++ 0x fügt einige der Funktionen hinzu, die D besitzt und denen C ++ fehlte (z. B.auto
und Lambdas), aber trotz all seiner Verbesserungen wird es immer noch nicht viel geben, was objektiv besser an C ++ als Sprache ist als D.Es steht außer Frage, dass es viele subjektive Gründe gibt, sich untereinander zu mögen, und die relative Unreife der Implementierung von D kann zuweilen ein Problem sein (obwohl sie sich in letzter Zeit sehr schnell verbessert hat - insbesondere seit die Repositorys auf Github verschoben wurden ). und das Fehlen von Bibliotheken von Drittanbietern kann definitiv ein Problem sein (obwohl die Tatsache, dass D leicht C-Funktionen aufrufen kann - und in geringerem Maße C ++ - Funktionen - definitiv das Problem mindert). Dies sind jedoch eher Probleme mit der Qualität der Implementierung als mit der Sprache selbst. Und da die Qualität der Implementierungsprobleme behoben ist, wird die Verwendung von D umso angenehmer.
Ich nehme also an, dass die kurze Antwort auf diese Frage "sehr wenig" ist. D ist als Sprache im Allgemeinen C ++ überlegen.
quelle
RAII- und Stapelspeicherauslastung
D 2.0 lässt RAII nicht auf dem Stapel zu, da der Wert des
scope
Schlüsselworts beim Zuweisen von Klasseninstanzen auf dem Stapel entfernt wurde.Sie können in D keine Vererbung vom Typ Wert durchführen, sodass Sie gezwungen sind, eine Heap-Zuordnung für jede Form von RAII vorzunehmen.
Das heißt, es sei denn, Sie verwenden
emplace
, aber die Verwendung ist sehr schmerzhaft, da Sie den Speicher manuell zuweisen müssen. (Ich habe es noch nicht für praktisch befunden, esemplace
in D zu verwenden .)quelle
C ++ zwingt Sie viel besser dazu, wortreich zu sein. Dies kann in Ihren Augen besser oder schlechter sein, je nachdem, ob Sie Inferenz oder Ausführlichkeit mögen.
Vergleichen Sie die Laufzeiterfassung in C ++ :
mit der gleichen Sache in D:
Beachten Sie beispielsweise die zusätzliche Ausführlichkeit von
template <typename ReturnType, typename... Args>
versus(F)
,Args...
versusArgs
,args...
versusargs
usw.C ++ ist besser oder schlechter gesagt ausführlicher.
Natürlich können Sie dies auch in D tun:
und sie würden fast identisch aussehen, aber dann würde dies ein erfordern
delegate
, während das Original jedes aufrufbare Objekt akzeptierte . (Die C ++ 0x-Version erfordert einstd::function
Objekt, so oder so, es ist ausführlicher und restriktiver in seinen Eingaben ... was gut sein könnte, wenn Sie Ausführlichkeit mögen, schlecht, wenn Sie dies nicht tun.)quelle
Ich weiß nicht viel über D, aber viele, viele C ++ - Programmierer, von denen ich weiß, dass sie es nicht mögen, und ich persönlich muss zustimmen, dass ich das Aussehen von D nicht mag und nicht näher darauf eingehen werde.
Um zu verstehen, warum D nicht mehr an Bodenhaftung gewinnt, müssen Sie zunächst verstehen, was Menschen an C ++ interessiert. Mit einem Wort, der Hauptgrund ist die Kontrolle. Wenn Sie in C ++ programmieren, haben Sie die vollständige Kontrolle über Ihr Programm. Möchten Sie die Standardbibliothek ersetzen? Du kannst. Möchten Sie unsichere Zeigermodelle erstellen? Du kannst. Willst du die Beständigkeit verletzen? Du kannst. Möchten Sie die Speicherzuordnung ersetzen? Du kannst. Möchten Sie rohen Speicher ohne Rücksicht auf seinen Typ kopieren? Wenn du wirklich willst. Möchten Sie von mehreren Implementierungen erben? Es ist deine Beerdigung. Zum Teufel, Sie können sogar Müllbibliotheken kaufen, so wie der Böhm-Sammler. Dann haben Sie Probleme wie die Leistung, die eng mit der Kontrolle zusammenhängt - je mehr Kontrolle ein Programmierer hat, desto optimierter kann er sein Programm erstellen.
Hier sind ein paar Dinge, die ich gesehen habe, als ich ein wenig recherchiert und mit ein paar Leuten gesprochen habe, die es versucht haben:
Einheitliche Typhierarchie. C ++ - Benutzer verwenden Vererbung sehr selten, die meisten C ++ - Programmierer bevorzugen die Komposition, und Typen sollten nur durch Vererbung verknüpft werden, wenn es einen sehr guten Grund dafür gibt. Das Konzept des Objekts verletzt dieses Prinzip stark, indem es jeden Typ verknüpft. Darüber hinaus verstößt es gegen eines der grundlegendsten Prinzipien von C ++ - Sie verwenden nur das, was Sie wollen. Das Fehlen einer Wahlmöglichkeit für das Erben von Object und die damit verbundenen Kosten stehen sehr stark im Widerspruch zu dem, wofür C ++ als Sprache steht, um dem Programmierer die Kontrolle über sein Programm zu geben.
Ich habe von Problemen mit Funktionen und Delegierten gehört. Anscheinend hat D sowohl Funktionen als auch Delegierte als zur Laufzeit aufrufbare Funktionstypen und sie sind nicht gleich, aber austauschbar oder ... etwas? Mein Freund hatte einige Probleme mit ihnen. Dies ist definitiv eine Herabstufung von C ++, die nur hat
std::function
und Sie sind fertig.Dann hast du Kompatibilität. D ist nicht besonders kompatibel mit C ++. Ich meine, keine Sprache ist mit C ++ kompatibel, seien wir ehrlich, mit Ausnahme von C ++ / CLI, das eine Art Betrug darstellt, aber als Eintrittsbarriere muss es erwähnt werden.
Dann gibt es noch ein paar andere Dinge. Lesen Sie zum Beispiel einfach den Wikipedia-Eintrag.
printf
ist eine der unsichersten Funktionen, die jemals entwickelt wurden, in derselben Familie wie große Probleme wiegets
in der alten C-Standard-Bibliothek. Wenn Sie im Stapelüberlauf danach suchen, werden Sie viele, viele Fragen im Zusammenhang mit dem Missbrauch finden. Grundsätzlichprintf
ist eine Verletzung von DRY- Sie geben den Typ in der Formatzeichenfolge an und geben ihn dann erneut an, wenn Sie ihm ein Argument geben. Eine Verletzung von DRY, bei der, wenn Sie etwas falsch machen, sehr schlimme Dinge passieren, wenn Sie eine Typendefinition von einer 16-Bit-Ganzzahl in eine 32-Bit-Ganzzahl ändern. Es ist auch überhaupt nicht erweiterbar - stellen Sie sich vor, was passieren würde, wenn jeder seine eigenen Formatspezifizierer erfinden würde. Die iostreams von C ++ sind möglicherweise langsam und die Auswahl des Operators ist möglicherweise nicht die beste. Die Benutzeroberfläche kann Arbeit gebrauchen. Grundsätzlich ist jedoch die Sicherheit der Iostreams gewährleistet und DRY wird nicht verletzt. Sie können problemlos erweitert werden. Das kann man nicht sagenprintf
.Keine Mehrfachvererbung. Das ist ganz und gar nicht der C ++ Weg. C ++ - Programmierer erwarten, dass sie die vollständige Kontrolle über ihr Programm haben, und die Sprache, die das erzwingt, wovon Sie nicht erben können, verstößt gegen dieses Prinzip. Darüber hinaus wird die Vererbung (noch) anfälliger, da der gesamte Code Ihres Benutzers plötzlich beschädigt wird, wenn Sie einen Typ von einer Schnittstelle in eine Klasse ändern, weil Sie eine Standardimplementierung oder ähnliches bereitstellen möchten. Das ist keine gute Sache.
Ein anderes Beispiel ist
string
undwstring
. In C ++ ist es bereits sehr schmerzhaft, zwischen ihnen konvertieren zu müssen. Unterstützt diese Bibliothek Unicode, und diese alte C-Bibliothek verwendet nurconst char*
unterschiedliche Versionen derselben Funktion, abhängig vom gewünschten String-Argumenttyp. Insbesondere die Windows-Header enthalten zum Beispiel einige äußerst irritierende Makros, um das Problem zu lösen, das häufig Ihren eigenen Code stören kann. Das Hinzufügendstring
zu der Mischung wird die Sache nur verschlimmern, da Sie jetzt anstelle von zwei Zeichenfolgentypen drei verwalten müssen. Wenn Sie mehr als einen Zeichenfolgentyp haben, werden die Wartungsprobleme zunehmen und sich wiederholender Code für Zeichenfolgen eingeführt.Scott Meyers schreibt:
Eine sprachgesteuerte Thread-Isolierung ist kein Plus. C ++ - Programmierer erwarten volle Kontrolle über ihre Programme, und die Sprache, die etwas erzwingt, entspricht definitiv nicht den Anweisungen des Arztes.
Ich werde auch die String-Manipulation während der Kompilierung erwähnen. D kann D-Code während der Kompilierung interpretieren. Dies ist kein Plus. Betrachten Sie die massiven Kopfschmerzen, die durch den relativ eingeschränkten Präprozessor von C verursacht werden, der allen erfahrenen C ++ - Programmierern bekannt ist, und stellen Sie sich dann vor, wie sehr diese Funktion missbraucht wird. Die Möglichkeit, D-Code zur Kompilierungszeit zu erstellen, ist großartig, sollte jedoch semantisch und nicht syntaktisch sein.
Außerdem ist ein gewisser Reflex zu erwarten. D hat eine Garbage Collection, die C ++ - Programmierer mit Sprachen wie Java und C # assoziieren werden, die in Philosophien ziemlich direkt dagegen stehen, und die syntaktischen Ähnlichkeiten werden sie auch in Erinnerung rufen. Dies ist nicht unbedingt objektiv zu rechtfertigen, aber es ist etwas, das auf jeden Fall beachtet werden sollte.
Grundsätzlich bietet es nicht so viel, wie C ++ - Programmierer es nicht können. Vielleicht ist es einfacher, ein faktorielles Metaprogramm in D zu schreiben, aber wir können bereits faktorielle Metaprogramme in C ++ schreiben. Vielleicht in D Sie können einen Compiler-ray-Tracer schreiben, aber niemand will wirklich , dass auf jeden Fall tun. Im Vergleich zu den grundlegenden Verstößen gegen die C ++ - Philosophie ist das, was Sie in D tun können, nicht besonders bemerkenswert.
Auch wenn diese Dinge nur Probleme auf der Oberfläche sind, bin ich mir ziemlich sicher, dass die Tatsache, dass D auf der Oberfläche überhaupt nicht wie C ++ aussieht, wahrscheinlich ein guter Grund dafür ist, dass viele C ++ - Programmierer nicht nach D migrieren. Möglicherweise muss D eine bessere Jobwerbung selbst erledigen.
quelle
std::function
und du bist fertig. Warum? Weil Sie zum Beispiel auch Funktionszeiger haben. Es ist genau dasselbe in D: Ds "Funktionen" sind Funktionszeiger, und Ds "Delegaten" sind die gleichen wie C ++std::function
(mit der Ausnahme, dass sie eingebaut sind). Es gibt nirgendwo ein "Downgrade" - und es gibt eine 1: 1-Entsprechung zwischen ihnen, daher sollte es nicht verwirrend sein, wenn Sie mit C ++ vertraut sind.Eine Sache, die ich in C ++ schätze, ist die Fähigkeit, ein Funktionsargument oder einen Rückgabewert als C ++ - Referenz anstelle eines Zeigers zu dokumentieren, was impliziert, dass ein Nichtwert verwendet
null
wird.D-Version:
C ++ Version:
Um fair zu sein, können Sie C ++ sehr nahe kommen, indem Sie
A
ein D erstellenstruct
und dasfoo()
-argument als a markierenref
(Klassen sind Referenztypen und Strukturen sind Werttypen in D, ähnlich wie in C #).Ich glaube, es gibt einen Plan,
NonNullable
stattdessen eine Vorlage für Klassen als D-Standard-Bibliothekskonstrukt zu erstellen . Trotzdem mag ich die Kürze von nur imType&
Vergleich zuNonNullable(Type)
und würde es vorziehen, als Standard nicht nullbar zu sein (Rendern von so etwas wieType
undNullable(Type)
). Aber es ist zu spät, um das für D zu ändern, und ich komme jetzt vom Thema ab.quelle
ref
, um den gleichen Effekt wie in C ++ zu erzielen&
. Der einzige große Unterschied besteht darin, dass Sieref
keine Zeit benötigen, auch wenn dies der Fall istconst
.Das Wichtigste, was C ++ "besser macht" als D, ist die Anbindung an Legacy-Bibliotheken . Verschiedene 3D-Engines, OpenCL und Ähnliches. Da D neu ist, stehen wesentlich weniger verschiedene Bibliotheken zur Auswahl.
Ein weiterer wichtiger Unterschied zwischen dem C ++ und dem D ist, dass der C ++ mehrere finanziell unabhängige Anbieter hat, aber seit 2014 hat der D praktisch nur noch einen , das 2-Mann-Team, das ihn geschaffen hat. Es ist interessant, dass das "Prinzip der zweiten Quelle" , wonach Projekte niemals von Technologie abhängen sollten, Komponenten, die nur einen einzigen Anbieter haben, auch für Software zu gelten scheint.
Zum Vergleich: Die erste Version des Ruby-Interpreters wurde vom Erfinder von Ruby, dem Yukihiro Matsumoto, geschrieben, aber der Mainstream-Ruby-Interpreter der Ära 2014 wurde von anderen praktisch von Grund auf neu geschrieben. Daher kann Ruby als eine Sprache angesehen werden, die mehr als einen finanziell unabhängigen Anbieter hat. D hingegen kann eine großartige Technologie sein, hängt jedoch von den wenigen Entwicklern ab, die sie entwickeln.
Die Geschichte von Java zeigt, dass selbst wenn eine Technologie, in diesem Fall Java, einen guten, aber einzigen Finanzier hat, das Risiko groß ist, dass die Technologie unabhängig von der großen Anzahl von Unternehmensbenutzern im Wesentlichen verloren geht. Ein Zitat der Apache Software Foundation , in der die EG für "Executive Committee" steht:
Oracle hat der EC eine Java SE 7-Spezifikationsanforderung und -Lizenz zur Verfügung gestellt, die sich selbst widersprechen, den Vertrieb unabhängiger Implementierungen der Spezifikation stark einschränken und vor allem den Vertrieb unabhängiger Open Source-Implementierungen der Spezifikation untersagen.
Als historische Anmerkung kann gesagt werden, dass Java-Applets jahrelang vor der Entwicklung von HTML5-WebGL eine hardwarebeschleunigte 3D-Leinwand hatten. Das Problem mit der Startgeschwindigkeit von Java-Applets hätte gelöst werden können, wenn Java ein Community-Projekt gewesen wäre, aber die Führungskräfte des einzigen Finanziers von Java, Sun Microsystems, fanden es nicht wichtig genug, die Java-Implementierung zu reparieren. Das Endergebnis: HTML5-Canvas von mehreren Anbietern als Replikat der Java-GUI-Frameworks (Swing usw.). Interessanterweise hat die Programmiersprache Python auf der Serverseite die gleichen Vorteile, die Java versprochen hat: einmal schreiben, auf jedem Server ausführen, unabhängig von der Hardware, vorausgesetzt, die Python-Anwendung ist nicht zu Maschinencode kompiliert. Der Python ist ungefähr so alt / jung wie der Java, aber im Gegensatz zum Java
Zusammenfassung:
Bei der Bewertung von Technologien für den produktiven Einsatz sind die wichtigsten Eigenschaften von Technologien die Menschen, die sie entwickeln, der soziale Prozess, in dem die Entwicklung stattfindet, und die Anzahl der finanziell unabhängigen Entwicklungsteams.
Ob es vorteilhafter ist, Technologie T1 gegenüber Technologie T2 zu verwenden, hängt von den Anbietern der Technologien ab und ob Technologie T1 es ermöglicht, projektbezogene Probleme billiger zu lösen als T2. Wenn beispielsweise das Problem eines einzelnen Anbieters ignoriert würde, wäre Java für Informationssysteme eine "bessere" Technologie als C ++, da Java-Binärdateien beim Deployment auf neue Hardware und bei der Entwicklung von Software zur Speicherverwaltung nicht neu kompiliert werden müssen ist für Java kleiner als für C ++. Projekte, die von Grund auf neu entwickelt wurden, z. B. Projekte, die nicht von anderen Bibliotheken abhängen, sind möglicherweise in D günstiger zu entwickeln als in C ++. Andererseits hat C ++ mehrere Anbieter und ist daher auf lange Sicht weniger riskant . (Das Java-Beispiel, in dem Sun Microsystems fast in Ordnung war,
Eine mögliche Problemumgehung für einige der C ++ - Einschränkungen
Eine der möglichen Problemumgehungen für einige der Einschränkungen von C ++ ist die Verwendung eines Entwurfsmusters, bei dem die anfängliche Aufgabe in Teile zerlegt und die Teile "sortiert" werden (klassifiziert, gruppiert, geteilt, andere-nette-Wörter-für- das Gleiche) zu 2 Klassen: Steuerlogik bezogene Aufgaben , bei denen Speicherzugriffsmuster keine Lokalität zulassen; Signalverarbeitungsähnliche Aufgaben , bei denen die Lokalität leicht zu erreichen ist. Die signalverarbeitenden "Like" -Aufgaben können als eine Reihe relativ vereinfachter Konsolenprogramme implementiert werden. Die Aufgaben im Zusammenhang mit der Steuerlogik werden alle in einem einzelnen Skript ausgeführt, das in Ruby oder Python oder in einer anderen Form geschrieben ist, bei der der Komfort der Softwareentwicklung Vorrang vor der Geschwindigkeit hat.
Um eine kostspielige Initialisierung von Betriebssystemprozessen und das Kopieren von Daten zwischen Betriebssystemprozessen zu vermeiden, kann der Satz kleiner C ++ - Konsolenanwendungen als einzelnes C ++ - Programm implementiert werden, das vom Ruby / Python / etc als "Servlet" gebootet wird. Skript. Der Ruby / Python / etc. Skript fährt das Servlet vor dem Beenden herunter. Kommunikation zwischen dem "Servlet" und dem Ruby / Python / etc. Das Skript findet über eine Linux Named Pipe oder einen ähnlichen Mechanismus statt.
Wenn sich die anfängliche Aufgabe nicht leicht in Teile aufteilen lässt, die in die beiden oben genannten Klassen eingeteilt werden können, besteht ein Versuch darin, das Problem neu zu formulieren, sodass sich die anfängliche Aufgabe ändert.
quelle