it-swarm-eu.dev

Warum sollte ich C ++ 11 lernen, nachdem ich C und C ++ gekannt habe?

Ich bin ein Programmierer in C und C++, obwohl ich mich nicht an eine der beiden Sprachen halte und eine Mischung aus beiden schreibe. Manchmal ist es offensichtlich besser, Code in Klassen zu haben, möglicherweise mit Überladung des Operators oder Vorlagen und der ach so großartigen STL. Manchmal ist die Verwendung eines einfachen C-Funktionszeigers viel besser lesbar und klarer. So finde ich Schönheit und Praktikabilität in beiden Sprachen. Ich möchte nicht auf die Diskussion über "Wenn Sie sie mischen und mit einem C++ - Compiler kompilieren, ist es keine Mischung mehr, es ist alles C++" eingehen. Ich denke, wir alle verstehen, was ich meine durch Mischen. Auch ich möchte nicht über C vs C++ sprechen, diese Frage dreht sich alles um C++ 11.

C++ 11 führt meiner Meinung nach wesentliche Änderungen in der Funktionsweise von C++ ein, hat jedoch viele Sonderfälle, Ausnahmen und Unregelmäßigkeiten eingeführt, die das Verhalten verschiedener Funktionen unter verschiedenen Umständen ändern und die Mehrfachvererbung einschränken, Bezeichner, die als Schlüsselwörter fungieren, Erweiterungen von String-Literalen, Erfassung von Lambda-Funktionsvariablen usw.

Ich weiß, dass irgendwann in der Zukunft, wenn Sie C++ sagen, jeder C++ 11 annehmen würde. Ähnlich wie wenn Sie heutzutage C sagen, meinen Sie höchstwahrscheinlich C99. Das bringt mich dazu, C++ 11 zu lernen. Wenn ich weiterhin Code in C++ schreiben möchte, muss ich diese Funktionen möglicherweise irgendwann verwenden, nur weil meine Kollegen dies getan haben.

Nehmen Sie zum Beispiel C. Nach so vielen Jahren lernen und schreiben immer noch viele Menschen Code in C. Warum? Weil die Sprache gut ist. Was gut bedeutet, ist, dass es vielen Regeln folgt, um eine gute Programmiersprache zu erstellen. Abgesehen davon, dass C leistungsstark ist (was leicht oder schwer ist, sind fast alle Programmiersprachen), ist C regulär und hat, wenn überhaupt, nur wenige Ausnahmen. C++ 11 glaube ich jedoch nicht. Ich bin nicht sicher, ob die in C++ 11 eingeführten Änderungen die Sprache verbessern.

Die Frage ist also: Warum sollte ich C++ 11 lernen?

28
anon

Sie sollten es lernen, wenn Sie denken, dass Sie es in Zukunft wissen müssen, um einen Job zu bekommen. Wenn Sie sicher sind, dass Sie als C/C++ [und was auch immer Sie sonst wissen] in der Belegschaft marktfähig bleiben, lernen Sie es nicht. Wenn Ihr Chef Sie auffordert, C++ 11 zu verwenden, sagen Sie "Nein, das mache ich nicht". Wenn er dich feuert, geh woanders arbeiten. Lernen Sie C++ 11, wenn Sie vorhersehen, dass Sie bald keine zufriedenstellende Beschäftigung mit den Fähigkeiten finden werden, die Sie derzeit kennen.

Wollte meine Begründung klarstellen: Ich bin kein Anti-C++ 11. Wenn Sie nur sagen, Sie könnten die Frage des OP auf "Warum sollte ich X lernen" verallgemeinern. Ich habe nie ML, Schema oder Haskell gelernt, weil ich einen Job bei C und C++ habe. Ich bin mir sicher, dass diese Sprachen für jemanden nützlich sind, aber sie sind für mich nicht von Vorteil, wenn ich sie gerade lerne. Wenn mir jemand gutes Geld zum Programmieren in ML anbietet, könnte ich versuchen, es zu lernen.

24
Timmah

Es ist einfach. C++ 11 macht Code erheblich einfacher, sauberer zu schreiben und schneller.

nullptr ist eine VAST Verbesserung gegenüber dem alten 0. Es ist typsicher und konvertiert nicht, wenn es nicht anders sein sollte als 0. Es ist eine gute Sache, die nullptr nicht in eine int konvertiert. Es macht überhaupt keinen Sinn, dass das passiert. Wissen Sie, was das C++ - Komitee gefunden hat, als es versucht hat, #define NULL nullptr? Zeug wie char c = NULL;. Wie schrecklich ist das? Der einzige Grund, warum es hier eine Ausnahme gibt, ist, dass bool als integraler Typ betrachtet wird, was völlig falsch ist - aber das gab es zuvor in C++ und in C. Die Tatsache, dass nullptr dies nicht tut konvertieren ist gut, es ist großartig und du solltest es lieben.

Oder wie wäre es mit Wertreferenzen und variablen Vorlagen? Schnellerer, allgemeinerer Code. Das ist genau dort ein totaler Gewinn.

Wie wäre es mit den Verbesserungen der Bibliothek? Sachen wie function, unique_ptr und shared_ptr sind so viel besser als vorher, dass man nicht behaupten kann, dass der C++ 03-Weg besser war.

#define adding_func(x, y) ((x)+(y))

Nicht einmal im entferntesten gleichwertig. Makros sind aus sechs Milliarden Gründen schlecht. Ich werde hier nicht alle zitieren, aber es ist bekannt, dass Makros für so ziemlich alle Zwecke vermieden werden sollten, für die sie möglicherweise vermieden werden können. Was wirst du tun, wenn es ist?

#define add_twice(x) (x + x)

Oh, warte, ich hoffe du hast nicht erhöht oder so etwas auf x. Womit die Template-Funktionsversion völlig immun ist. Ich hoffe auch, dass Sie Namespaces zum Beispiel nicht schätzen.

Dann öffnen Sie sich einer Welt undefinierten Verhaltens für die Verwendung externer Variablen, deren Bereiche bereits abgeschlossen sind.

In einer funktionalen API, z. STL-Algorithmen, dann ist die Referenz in Ordnung. Wenn es sich um einen gespeicherten Rückruf handelt, müssen Sie nach Wert erfassen. Unabhängig davon, welche Dokumentation Sie über die Funktion haben, sollte klar angegeben werden, welche erforderlich ist. Die Tatsache, dass der Code in einem Lambda geschrieben ist, spielt für das Problem der Bezugnahme auf lokale Variablen keine Rolle. Wenn Sie ein reguläres Funktionsobjekt übergeben, treten genau dieselben Probleme auf. Und es ist kein Problem. Überhaupt. Weil es von Natur aus offensichtlich ist, wann Sie auf lokale Variablen verweisen können und wann nicht.

Nehmen Sie zum Beispiel C. Nach so vielen Jahren lernen und schreiben immer noch viele Menschen Code in C. Warum?

Es gibt viele Menschen, die sich morgens nicht die Zähne putzen. Es gibt viele Mörder, Vergewaltiger und Prostituierte. Und Politiker. Menschen, die Selbstmord begehen. Würden Sie argumentieren, dass dies diese Aktivitäten gut oder nützlich macht? Natürlich nicht. Es ist ein logischer Irrtum, dass es gut oder nützlich sein muss, nur weil es jemand getan hat.

C wird noch aus drei Gründen geschrieben: weil C++ eine Hündin ist, die implementiert werden muss, zum Beispiel im Embedded- oder Kernel-Modus; weil ältere Codebasen in C geschrieben sind und zu viel für ein Upgrade kosten würden, obwohl selbst das angesichts der hervorragenden C-Interop von C++ fraglich ist; und weil die Leute, die es schreiben, nicht wissen, wie man programmiert. Das ist es. Es gibt keinen anderen Grund, C zu schreiben.

Wenn Sie C oder C++ im alten Stil verwenden, werden Sie nicht viele Ausnahmen finden.

Wie wäre es mit den erbärmlichen Arrays im C-Stil für ein einfaches Beispiel? Die Anzahl der Personen, die keine Arrays und Zeiger direkt in den Kopf bekommen können, ist obszön. Ganz zu schweigen von der Tatsache, dass die C-Standard-Bibliothek unglaublich unsicher ist.

Ihre Kernargumente sind voller logischer Irrtümer und Missverständnisse.

85
DeadMG

C++ 11 ist keine neue Sprache. Es ist nur eine Erweiterung/Modifikation von C++, die Sie bereits kennen. C++ 11 besteht wie jede andere Programmiersprache aus Funktionen. Viele von ihnen waren von früher dort, einige von ihnen sind neu. Aber Ihre Frage ist wirklich, sollte ich alle Funktionen der Sprache lernen (in diesem Fall C++ 11) oder mich nur mit 90% davon vertraut machen?

IMO, auch wenn Sie nicht die gesamte Sprache verwenden, sollten Sie zumindest nachlesen, was die neuen Funktionen für Sie tun. Viele von ihnen wurden eingeführt, um das Schreiben von Bibliotheks-/Framework-Code (insbesondere Vorlagen) zu vereinfachen (z. B. bevor eine perfekte Weiterleitung in C++ 11 unmöglich war). Wenn Sie diese Funktion jedoch noch nie benötigt haben, haben Sie wahrscheinlich die Chance gewonnen Beachten Sie nicht, dass diese Funktionen in C++ 11 hinzugefügt wurden.

Auf der anderen Seite, wenn Sie zuvor versucht haben, Bibliotheks-/Kerncode zu schreiben, der einige der STL/Boost-Funktionen nachahmt, und sich durch die Sprache eingeschränkt fühlen, weil Sie zu 95% zu einer sehr coolen, eleganten Lösung gekommen sind Sie wurden gestoppt, weil Sie herausgefunden haben, dass die Sprache einfach nicht das unterstützt, was Sie wollen. Sie werden die wirklich beeindruckende Leistung von C++ 11 erkennen. Seit unser Team auf VS2010 aktualisiert hat (und wir dabei Boost entdeckt haben), konnte ich einen verrückten, großartigen Code herausbringen, der vor Dingen wie R-Wert-Referenzen und der Weiterleitung von Vorlagenparametern einfach unmöglich wäre.

Auch Dinge wie Lambdas mögen fremd aussehen, aber sie führen kein neues Konstrukt ein. Stattdessen machen sie das, was wir früher hatten, so viel einfacher zu schreiben. Bisher musste jede Lambda-Funktion eine separate Klasse sein. Jetzt ist es nur noch {... Code ...}. Liebe es.

Der Schlüssel ist, sich diese Funktionen nicht anzusehen und darüber nachzudenken, wie entmutigend die Liste ist. Verwenden Sie stattdessen C++ wie gewohnt. Wenn Sie auf ein Szenario stoßen, in dem diese neuen C++ 11-Funktionen nützlich sind (mehr als 90% der Benutzer werden diesen Punkt nie erreichen), werden Sie sich sehr über die Erweiterung freuen zur Sprache wurde getan. Im Moment würde ich vorschlagen, dass Sie nur genug über die Sprache lernen, um zu wissen, was da ist, und nicht unbedingt, wie man alles benutzt.

29
DXM

Ist es so schwierig, eine Funktion zu schreiben, dass Sie den Inhalt der Funktion in den Code schreiben müssen, ohne ihm einen Namen zu geben?

Wenn Sie dies tun, scrollen Sie nach oben oder öffnen eine neue Quelldatei und fügen dort die Definition der Funktion hinzu. Dann müssen Sie zurückgehen und mit dem fortfahren, woran Sie gearbeitet haben, was Sie bis zu einem gewissen Grad ablenkt.

Wenn andere Leute Ihren Code lesen, kann ein Lambda in einigen Fällen selbstdokumentierender sein, anstatt zu sagen: "Oh, was macht diese Funktion?" Wenn Sie zu seiner Erklärung springen, können Sie sich nur ansehen, was es an seiner Stelle tut.

Es gibt einen netten Vortrag von Herb Sutter über Lambdas, vielleicht kann er Sie besser überzeugen:

http://channel9.msdn.com/events/PDC/PDC10/FT1

Warum schreibst du den Code nicht einfach dort, anstatt ihn zu einer Lambda-Funktion zu machen?

Weil Sie dies nicht tun können, wenn Sie STL-Algorithmen oder eine von Ihnen verwendete Funktion verwenden, für die Sie eine Funktion übergeben müssen.

#define adding_func (x, y) ((x) + (y))

Es gibt keine Möglichkeit, diese Verwendung anstelle von Lambdas zu rechtfertigen. Sie können Ihren Code nicht überall mit Makros füllen. Makros und Funktionen haben unterschiedliche Zwecke, und eines ist im Allgemeinen kein Ersatz für das andere.

template<class Lhs, class Rhs>
auto adding_func(const Lhs &lhs, const Rhs &rhs)
                -> decltype(lhs+rhs) {return lhs + rhs;}

Ich stimme zu, das ist hässlich. Ich erinnere mich jedoch, dass ich sagte: "Warum zum Teufel sollte ich den Typ dieses Ausdrucks herausfinden, obwohl der Compiler darauf schließen kann?" in vielen Fällen. Dies könnte in diesen Momenten sehr hilfreich sein.

Zusammenfassend:

Obwohl die neuen Funktionen von C++ 11 in ihrer Syntax hässlich erscheinen, kann man sich in kurzer Zeit daran gewöhnen. Jedes neue Sprachkonstrukt ist zunächst schwer zu lernen; Stellen Sie sich das erste Mal vor, dass Sie gelernt haben, eine ganze Klasse zu schreiben: Fügen Sie die Deklaration in die Header-Datei ein, ohne das zusätzliche Semikolon am Ende zu vergessen, und fügen Sie die Definitionen in die Quelldatei ein, einschließlich der Header-Datei, und stellen Sie gleichzeitig sicher, dass sie einen Schutz zum Verhindern hat mehrere Einschlüsse, wobei der Operator für die Bereichsauflösung in den Elementfunktionsdeklarationen usw. nicht zu vergessen ist ...

Aber ich bin mir ziemlich sicher, dass Sie sich nach dem Schreiben einiger Klassen daran gewöhnen und nicht über die Komplexität dieses Prozesses nachdenken: Weil Sie wissen, dass eine Klasse Ihre Arbeit als Programmierer viel einfacher macht, und die Die Nützlichkeit, die Sie mit diesem neuen Konstrukt verdienen, ist viel größer als der Nutzenverlust während der Zeit, als Sie versuchten, die Sprache zu lernen. Ich denke, dies kann der Grund sein, warum man versuchen sollte, C++ 11 auf ähnliche Weise zu lernen oder zu verwenden.

18
loudandclear

Tatsächlich hat das OP einige Punkte, wie die meisten Antworten. Aber sie haben eine "entfernte" Sicht. C++ (einschließlich C-Teilmenge) hat eine lange Geschichte, in der im Laufe der Zeit eine Reihe von Funktionen hinzugefügt wurden, von denen einige mehr oder weniger häufig verwendet wurden und - durch ihre Verwendung und Fehler - in andere und andere perfektioniert wurden.

Manchmal kommt es vor, dass nach der Einführung eines neuen Features ein altes mehr benötigt wird oder sich im Widerspruch dazu fühlt. Eine "saubere" Sprache sollte so wie sie ist selbstkonsistent sein und nicht mehr benötigte Funktionen sollten entfernt werden.

Aber das Hinzufügen zerstört nichts. Durch das Entfernen (oder Ändern) wird vorhandener Code beschädigt, der sich noch in der Produktion befindet. Unabhängig davon, welche Funktion Sie hinzufügen, müssen Sie darauf achten, vorhandenen Code nicht zu beschädigen (insbesondere nicht zu brechen lautlos, es dazu bringen, verschiedene Dinge zu tun, wie beabsichtigt).

Musst du das alles lernen? Ja, weil alle Funktionen - ob gut oder schlecht, früher oder später - verwendet werden. Ob dies eine gute Sache für die "Qualität" der Sprache ist (zugeben, dass es ein Ziel Maß dafür gibt), ist eine andere Geschichte: Wie lange sollte die Abwärtskompatibilität erhalten bleiben? Es ist schwer, eine Antwort zu finden, wenn jemand 3 Jahre und ein anderer 50 Jahre sagt.

Die Alternative, um C++ "regelmäßiger" zu halten, besteht darin, es öfter mit einem Neustart zu unterbrechen. Aber es wird kein C++ mehr sein.

Es gibt auch Versuche, dies zu tun (denken Sie beispielsweise an D: viel viel orthogonaler als C++ (sogar 11) tatsächlich), aber wie beliebt sind sie? Einer der Gründe für ihre Schwierigkeit, Schwung zu haben, ist die Inkompatibilität mit vielen vorhandenen Codes, die noch ausgeführt werden müssen.

C++ 11 ist für mich eindeutig ein Kompromiss zwischen neuen Anforderungen und Abwärtskompatibilität. Dies führte zu einer gewissen "Unordnung" der Spezifikationen und der Implementierung. Bis die Kosten für diese "Unordnung" geringer sind als die Kosten für Inkompatibilität ... müssen Sie mit diesem Kompromiss abreisen.

Wenn Sie es nicht mehr tolerieren können, ... ziehen Sie besser eine andere jüngere Sprache in Betracht. C++ kann in diesem Sinne einfach nicht vereinfacht werden. Nicht in diesem Alter.

8

Selbst wenn Sie die neuen C++ 11-Funktionen ignorieren, profitieren Sie davon, da sie von der C++ - Standardbibliothek verwendet werden. Zum Beispiel in C++ 98 mit einer Variablen vom Typ vector<string> war aufgrund der Anzahl der Kopien, die erstellt werden mussten, wenn der Vektor wächst, möglicherweise eine Leistungskatastrophe. Mit dem C++ 11-Verschiebungskonstruktor ist dies kein Problem. Tatsächlich wünschte ich mir, C++ 11 hätte uns mehr neue Funktionen gebracht, nicht weniger - insbesondere in der Standardbibliothek.

7

Nach so vielen Jahren lernen und schreiben immer noch viele Menschen Code in C. Warum? Weil die Sprache gut ist.

Erstens lernen die meisten Schüler heutzutage Java oder .NET, nicht C. Zweitens verwenden die Leute C immer noch nicht nur wegen seiner Vorteile als Sprache, sondern hauptsächlich, weil es eine große Menge gibt von vorhandener in C geschriebener Software, die gewartet und erweitert werden muss, und weil in vielen Fällen (z. B. eingebettete Plattformen) nur ein C-Compiler vorhanden ist. Dies sind übrigens einige der Gründe, warum die Leute immer noch COBOL schreiben.

Es ist sehr selten, dass ein Programmierer in der Branche anfängt, an einem brandneuen Projekt zu arbeiten, das nicht an eine vorhandene Codebasis gebunden ist, und alleine weiterarbeitet. Der Grund für das Erlernen von C++ 11 ist, dass Sie sich wahrscheinlich mit Code befassen müssen, der von anderen Personen geschrieben wurde und die neuen Funktionen verwendet. Außerdem wurden die hinzugefügten Funktionen aus einem bestimmten Grund hinzugefügt. Sobald Sie sie gelernt und verwendet haben, werden Sie sie möglicherweise zu schätzen wissen.

6
Dima
  • Die Assembly wurde erstellt, weil die Leute keinen Maschinencode schreiben wollten
  • C wurde erstellt, weil die Leute nicht gerne Assembly schreiben
  • C++ wurde erstellt, weil die Leute nicht gerne C schreiben
  • C++ 11 wurde erstellt, weil die Leute nicht gerne C++ schreiben

Sie werden zu einem Punkt in Ihrer C++ - Karriere kommen, an dem Sie sich sagen: "Ich wünschte, Funktoren wären einfacher" oder "Warum ist NULL ein Int?" und dann werden Sie C++ 11 verstehen.

5
Pubby

Sie sollten C++ 11 lernen, da Sie mit den hinzugefügten Funktionen besseren Code schreiben können. Einige Leute haben die Typensicherheit von NULL-Zeigern und Lambdas erwähnt, die sehr nett sind. Ich möchte jedoch auf die meiner Meinung nach dramatischste Änderung in C++ 11 aufmerksam machen, insbesondere in einer großen Produktionsumgebung: die Bewegungssemantik.

C++ 11 unterstützt separate Begriffe wie "Verschieben" und "Kopieren". In regulärem C++ haben wir nur den Operator =, der im Grunde beides macht. Aber wirklich, wir drücken zwei getrennte Ideen mit einem Bediener aus, was gefährlich ist.

Das offensichtlichste Beispiel dafür, wo dies nützlich ist, ist das neue unique_ptr. Es hat die besten Funktionen des alten auto_ptr und scoped_ptr. Angenommen, wir möchten einen Zeiger haben, der garantiert der einzige Zeiger ist, der auf ein Objekt zeigt. Wie gehen wir mit a = b um? Nun, bevor wir feststeckten, konnten Sie es entweder vollständig verbieten (als scoped_ptr) oder wir konnten das tun, was auto_ptr tut, wenn a = b b das Eigentum stiehlt. Dieses Verhalten von auto_ptr ist sehr verwirrend, da sich a = b tatsächlich b ändert. unique_ptr behandelt dies: a = b ist nicht erlaubt, aber Sie haben a = std :: move (b), um das Eigentum zu stehlen. Wie ist das nützlich? Wobei es eine separate (überladene) Version von Swap gibt, die die Verschiebungssemantik anstelle der Kopiersemantik verwendet. Dies bedeutet, dass unique_ptr problemlos ausgetauscht werden kann. Dies bedeutet, dass unique_ptr im Gegensatz zu auto_ptr sicher in einem Container verwendet werden kann und dann sort sagt. unique_ptr ist im Grunde das A und O der sicheren Speicherverwaltung, wenn Sie nicht mehrere Zeiger auf dasselbe Objekt benötigen.

Ein weiteres gutes Beispiel: Angenommen, Sie haben ein Objekt, das nicht kopiert werden kann. Dies ist in einer Reihe von Situationen nützlich. Sie können dieses Objekt niemals von einer Funktion zurückgeben, da es nach Beendigung der Funktion alles kopiert, was Sie zurückgeben. Das Ironische ist, dass der Compiler dies normalerweise tatsächlich optimiert (d. H. Am Ende wird nichts kopiert, der Rückgabewert wird an der Adresse der eventuellen Zuweisung erstellt). Dies hat jedoch nichts damit zu tun, warum wir es nicht kopierbar gemacht haben. Wenn Sie von einer Funktion zurückkehren, wird das Objekt nur vom inneren Funktionsbereich nach außen verschoben. Sie können jetzt Objekte schreiben, die nicht kopierbar, aber beweglich sind, und diese Objekte können von Funktionen zurückgegeben werden.

Die Verschiebungssemantik erleichtert das Schreiben von Code, der nicht ausläuft und threadsicher ist.

4
Nir Friedman

Lernen ist immer von Vorteil. Wissen ist Macht.

Das ist im Grunde die Antwort. Alles andere ist nur ein Detail darüber, wie genau Sie davon profitieren können und welche Befugnisse Sie haben, wenn Sie es kennen, und es sind so viele, dass jede Aufzählung unvollständig wäre.

Ein Beispiel ist Ihre eigene Frage. Sie könnten es nicht einmal fragen, ohne zumindest ein bisschen davon zu lernen.

Und wie ich bereits sagte - das eigentliche Problem ist nicht, warum man lernt, sondern warum man benutzt. Und das ist eine ganz andere Frage.

4
littleadv