Rust oder C++: was der Wechsel wirklich kostet
Rust nimmt dem Review eine ganze Fehlerklasse ab und verlangt dafür Einarbeitungszeit pro Person sowie ein Ökosystem, das nicht überall so dicht ist wie das von C++.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Der Vergleich scheitert meistens an der falschen Gegenseite
Der Anlass ist fast immer derselbe: Ein Absturz im Feld, dahinter ein Zugriff auf bereits freigegebenen Speicher, und in der nächsten Besprechung liegt der Vorschlag auf dem Tisch, das Bauteil in Rust neu zu schreiben. Verglichen wird dann Rust gegen C++ aus der Zeit von new und delete. Das ist nicht die Gegenseite, gegen die du antrittst, denn ein Team, das intelligente Zeiger, Container und RAII konsequent nutzt und seine Testsuite unter AddressSanitizer laufen lässt, hat dieselbe Fehlerklasse bereits stark eingedämmt.
Teuer wird die Entscheidung in beide Richtungen. Wer wechselt, ohne die Einarbeitung als eigenen Posten einzuplanen, hat nach drei Monaten ein halb fertiges Bauteil, eine zweite Werkzeugkette im Bau und genau eine Person, die den Code versteht. Wer nicht wechselt und die vorhandenen Werkzeuge trotzdem nicht einschaltet, hat die alte Fehlerklasse behalten und dafür nichts gespart.
Die Frage lautet deshalb nicht, welche Sprache besser ist, sondern welche Fehler euch im letzten Jahr tatsächlich Geld gekostet haben, wie lange der betroffene Code noch leben soll und ob die Bibliotheken, an denen euer Produkt hängt, in der neuen Welt überhaupt vorhanden sind.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Rust und modernes C++ nebeneinander
Verglichen wird hier nicht mit C++ aus den neunziger Jahren, sondern mit einem Team, das intelligente Zeiger, Container, Sanitizer und statische Analyse tatsächlich einsetzt. Nur gegen diese Gegenseite ist die Rechnung ehrlich.
Rust
prüft Eigentum und Ausleihen beim Übersetzen, bringt eine Werkzeugkette aus einer Hand mit und hat ein junges Ökosystem
Modernes C++
intelligente Zeiger, Container und RAII, dazu Sanitizer und statische Analyse, darunter dreißig Jahre Bibliotheken
| Entscheidungsfrage | Rust | Modernes C++ |
|---|---|---|
| Was fängt der Compiler ab, bevor der Code überhaupt läuft? | Stärke Zugriff nach der Freigabe, doppelte Freigabe, baumelnde Referenzen und gleichzeitiger Schreibzugriff aus zwei Threads sind in sicherem Rust Übersetzungsfehler, unabhängig davon, ob ein Test den Pfad je erreicht. | Kommt darauf an Sanitizer und statische Analyse finden dieselben Fehler zuverlässig, aber erst zur Laufzeit und nur auf den Pfaden, die ein Testlauf tatsächlich durchläuft. |
| Wie viel Aufwand kosten Bauen und Abhängigkeiten im Alltag? | Stärke Cargo deckt Bauen, Abhängigkeiten, Tests, Formatierung und Lint mit je einem Befehl ab, und rustup verwaltet die Werkzeugkette selbst. Ein neues Projekt läuft in Minuten. | Schwäche CMake, dazu vcpkg oder Conan oder mitgelieferter Quelltext, clang-format, clang-tidy und ein Test-Framework. Jedes Projekt entscheidet das anders, und der erste Tag im Team geht oft dafür drauf, den Bau überhaupt zum Laufen zu bringen. |
| Findest du die Bibliotheken, an denen dein Produkt hängt? | Kommt darauf an Für Netzwerk, Serialisierung, Kryptografie, Parser und Kommandozeile ist die Lage gut und ausgereift. Bei Oberflächen, Numerik, Bildverarbeitung und Hersteller-SDKs endet es oft bei einer C-Bindung, die du selbst umhüllst. | Stärke Qt, OpenCV, Eigen, Boost und praktisch jedes Hersteller-SDK liegen als C++-Bibliothek vor, meistens mit Beispielen, Dokumentation und einem Ansprechpartner beim Hersteller. |
| Wie lange dauert es, bis jemand aus dem Team liefert? | Schwäche Wer C++ kann, schreibt nach wenigen Tagen kompilierenden Code. Bis jemand eigene Datenstrukturen entwirft, ohne gegen die Eigentumsregeln zu laufen, vergehen erfahrungsgemäß mehrere Wochen mit echtem Code. | Stärke Das Team kann es bereits. Fragen lassen sich am Nachbartisch klären, und neue Leute bringen die Sprache in der Regel mit. |
| Wie lange dauert eine Änderung bis zur Rückmeldung? | Kommt darauf an Ein vollständiger Bau dauert bei mittelgroßen Projekten Minuten, weil Generics für jeden Typ neu übersetzt werden und der Linker am Ende einen erheblichen Teil beansprucht. Cargo check, ein aufgeteilter Workspace und ein schnellerer Linker holen einen Großteil zurück. | Kommt darauf an Header-Abhängigkeiten führen zu ähnlich langen Bauzeiten. Vorübersetzte Header, ccache und zusammengefasste Übersetzungseinheiten sind dort der eingespielte Gegenzug. |
| Wie leicht besetzt du eine offene Stelle? | Schwäche Der Kreis der Leute mit mehrjähriger Rust-Erfahrung ist klein. Auf eine solche Stelle bewerben sich oft Leute, die die Sprache aus eigenem Antrieb gelernt haben, was fachlich gut sein kann, die Auswahl aber nicht größer macht. | Kommt darauf an Erfahrene C++-Leute findest du in jeder größeren Stadt. Gefragt und entsprechend teuer sind sie trotzdem, und wer C++ nur aus dem Studium kennt, bringt die Disziplin für Sanitizer und Guidelines nicht automatisch mit. |
Was fängt der Compiler ab, bevor der Code überhaupt läuft?
Zugriff nach der Freigabe, doppelte Freigabe, baumelnde Referenzen und gleichzeitiger Schreibzugriff aus zwei Threads sind in sicherem Rust Übersetzungsfehler, unabhängig davon, ob ein Test den Pfad je erreicht.
Sanitizer und statische Analyse finden dieselben Fehler zuverlässig, aber erst zur Laufzeit und nur auf den Pfaden, die ein Testlauf tatsächlich durchläuft.
Wie viel Aufwand kosten Bauen und Abhängigkeiten im Alltag?
Cargo deckt Bauen, Abhängigkeiten, Tests, Formatierung und Lint mit je einem Befehl ab, und rustup verwaltet die Werkzeugkette selbst. Ein neues Projekt läuft in Minuten.
CMake, dazu vcpkg oder Conan oder mitgelieferter Quelltext, clang-format, clang-tidy und ein Test-Framework. Jedes Projekt entscheidet das anders, und der erste Tag im Team geht oft dafür drauf, den Bau überhaupt zum Laufen zu bringen.
Findest du die Bibliotheken, an denen dein Produkt hängt?
Für Netzwerk, Serialisierung, Kryptografie, Parser und Kommandozeile ist die Lage gut und ausgereift. Bei Oberflächen, Numerik, Bildverarbeitung und Hersteller-SDKs endet es oft bei einer C-Bindung, die du selbst umhüllst.
Qt, OpenCV, Eigen, Boost und praktisch jedes Hersteller-SDK liegen als C++-Bibliothek vor, meistens mit Beispielen, Dokumentation und einem Ansprechpartner beim Hersteller.
Wie lange dauert es, bis jemand aus dem Team liefert?
Wer C++ kann, schreibt nach wenigen Tagen kompilierenden Code. Bis jemand eigene Datenstrukturen entwirft, ohne gegen die Eigentumsregeln zu laufen, vergehen erfahrungsgemäß mehrere Wochen mit echtem Code.
Das Team kann es bereits. Fragen lassen sich am Nachbartisch klären, und neue Leute bringen die Sprache in der Regel mit.
Wie lange dauert eine Änderung bis zur Rückmeldung?
Ein vollständiger Bau dauert bei mittelgroßen Projekten Minuten, weil Generics für jeden Typ neu übersetzt werden und der Linker am Ende einen erheblichen Teil beansprucht. Cargo check, ein aufgeteilter Workspace und ein schnellerer Linker holen einen Großteil zurück.
Header-Abhängigkeiten führen zu ähnlich langen Bauzeiten. Vorübersetzte Header, ccache und zusammengefasste Übersetzungseinheiten sind dort der eingespielte Gegenzug.
Wie leicht besetzt du eine offene Stelle?
Der Kreis der Leute mit mehrjähriger Rust-Erfahrung ist klein. Auf eine solche Stelle bewerben sich oft Leute, die die Sprache aus eigenem Antrieb gelernt haben, was fachlich gut sein kann, die Auswahl aber nicht größer macht.
Erfahrene C++-Leute findest du in jeder größeren Stadt. Gefragt und entsprechend teuer sind sie trotzdem, und wer C++ nur aus dem Studium kennt, bringt die Disziplin für Sanitizer und Guidelines nicht automatisch mit.
Was passt wann
- Wenn im Fehlerverzeichnis des letzten Jahres kaum Speicherfehler stehen und die Bibliotheken sitzen
- bleib bei C++ und steck den Aufwand in Sanitizer im Bauprozess und in eine strengere Konfiguration der statischen Analyse.
- Wenn ein Bauteil fremde Eingaben verarbeitet, lange lebt und schon zweimal mit einem Speicherfehler aufgefallen ist
- schreib genau dieses Bauteil in Rust neu und lass die Anwendung darum herum unangetastet.
- Wenn ihr ohnehin neu anfangt und niemand an ein bestimmtes C++-Framework gebunden ist
- nimm Rust und plan die Einarbeitung für zwei Personen als eigenen Posten ein, statt sie nebenher zu hoffen.
Fünf Fragen, und die Sprachwahl steht
- 01 Wie viele Fehler des letzten Jahres waren Speicherfehler? Darunter lohnt Rust selten.
- 02 Läuft C++ bei euch schon mit Sanitizern und clang-tidy? Dann ist der Abstand kleiner.
- 03 Hängt das Produkt an Qt, OpenCV oder einem Hersteller-SDK? Dann prüf die Bindung.
- 04 Können zwei Leute mehrere Wochen lernen, ohne dass ein Termin kippt? Sonst wird es eng.
- 05 Lebt der Code noch fünf Jahre? Erst dann zahlt sich die Einarbeitung überhaupt aus.
Was du nach dieser Seite ohne Bauchgefühl entscheidest
Die Abwägung besteht aus sechs Prüfungen, die sich alle an vorhandenen Daten beantworten lassen: am Fehlerverzeichnis, an der Abhängigkeitsliste, am Bauzeitprotokoll und am Kalender. Bauchgefühl brauchst du erst, wenn diese sechs kein eindeutiges Bild ergeben.
Die Fehlerklasse beziffern statt über Sprachen zu reden
Geh die Fehler des letzten Jahres durch und zähl, wie viele davon Zugriff nach der Freigabe, Pufferüberlauf, uninitialisierter Speicher oder ein Datenrennen waren. Diese Zahl ist der ganze Geschäftsfall. Liegt sie bei zwei, trägt der Wechsel sich nicht.
Sanitizer und Compilerprüfung auseinanderhalten
AddressSanitizer und ThreadSanitizer finden dieselben Fehler zuverlässig, aber zur Laufzeit und nur auf den Pfaden, die ein Test wirklich durchläuft. Der Borrow-Checker weist den Code beim Übersetzen ab, unabhängig von der Testabdeckung. Das ist eine andere Zusage, nicht dieselbe in besser.
Die Werkzeugkette mit einrechnen
Cargo deckt Bauen, Abhängigkeiten, Tests, Formatierung und Lint mit je einem Befehl ab. Auf der anderen Seite stehen CMake, dazu vcpkg oder Conan, clang-format, clang-tidy und ein Test-Framework, jedes mit eigener Konfiguration. Dieser Unterschied wirkt jeden Tag, die Sprachfrage nur beim Entwurf.
Die Bibliothekslage in deiner Nische prüfen
Schreib die fünf Bibliotheken auf, ohne die euer Produkt nicht startet, und such jede einzeln auf crates.io. Bei Qt, OpenCV, Eigen und Hersteller-SDKs für Feldbus, Kameras oder Antriebe endet die Suche oft bei einer C-Bindung, die du selbst umhüllst und für die du die Korrektheit selbst verantwortest.
Die Übersetzungszeit als Arbeitsbedingung behandeln
Rust baut langsam, weil Generics für jeden Typ neu übersetzt werden und am Ende der Linker steht. Cargo check für die Rückmeldung beim Schreiben, ein Workspace aus mehreren Crates und ein schnellerer Linker holen viel davon zurück. Wer das erst im dritten Sprint merkt, hat den Rhythmus des Teams schon verloren.
Die Personalfrage ehrlich stellen
Der Kreis der Leute mit mehrjähriger Rust-Erfahrung ist deutlich kleiner als der für C++. Die praktikable Antwort ist meistens nicht Einstellung, sondern Ausbildung im eigenen Team, und dafür brauchst du mindestens zwei Personen gleichzeitig, sonst hängt der ganze Code an einer.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Was der Compiler prüft und was er ausdrücklich nicht prüft
Sicheres Rust schließt beim Übersetzen aus: Zugriff auf freigegebenen Speicher, doppelte Freigabe, baumelnde Referenzen und gleichzeitigen Schreibzugriff auf denselben Wert aus zwei Threads. Dahinter stehen zwei Regeln. Jeder Wert hat genau einen Besitzer, und wenn dessen Gültigkeitsbereich endet, wird der Wert freigegeben. Und solange ein Wert ausgeliehen ist, gibt es entweder genau eine veränderliche Ausleihe oder beliebig viele lesende, nie beides gleichzeitig. Zugriffe über den Rand eines Bereichs hinaus fängt Rust zur Laufzeit ab und bricht kontrolliert ab, statt still in fremden Speicher zu schreiben.
Genauso wichtig ist die andere Liste. Nicht ausgeschlossen sind Logikfehler, Verklemmungen zwischen zwei Sperren, Speicher, der nie freigegeben wird, unbegrenzt wachsende Warteschlangen und Abbrüche aus einem unwrap heraus. Ganzzahlüberläufe brechen im Debug-Bau ab und laufen im optimierten Bau standardmäßig über. Und jeder unsafe-Block sowie jeder Aufruf in eine C-Bibliothek hinein hebt die Zusage genau an dieser Stelle auf, dort haftest du selbst.
Der ehrliche Satz für die Entscheidungsvorlage lautet deshalb: Rust nimmt euch eine Fehlerklasse ab, nicht die Fehler. Reviews braucht ihr weiterhin, für Fachlogik, Schnittstellenentwurf und Laufzeitverhalten. Was wegfällt, ist die Sorte Review, in der jemand mit dem Finger auf dem Bildschirm nachverfolgt, wer den Zeiger zuletzt besessen hat.
Modernes C++ ist der ehrlichere Gegner
Ein Großteil der klassischen Speicherfehler verschwindet, wenn eine Codebasis konsequent auf unique_ptr und shared_ptr statt auf new und delete setzt, auf Container statt auf rohe Felder, auf string_view und span statt auf Zeiger mit Längenangabe daneben. Die C++ Core Guidelines schreiben das aus, samt Begründung und Gegenbeispiel. Der Unterschied zu Rust ist nicht, dass es diese Regeln nicht gäbe, sondern dass sie niemand durchsetzt.
Dazu kommt der Werkzeugkasten. AddressSanitizer findet Zugriffe nach der Freigabe und über Puffergrenzen hinaus, UndefinedBehaviorSanitizer meldet vorzeichenbehaftete Überläufe und fehlerhafte Ausrichtung, ThreadSanitizer findet Datenrennen, clang-tidy prüft ein umfangreiches Regelwerk statisch. Die Testsuite einmal unter AddressSanitizer und UndefinedBehaviorSanitizer in den Bauprozess zu hängen ist ein Tagesprojekt, kein Quartalsprojekt, und es ist die mit Abstand billigste Maßnahme in dieser ganzen Abwägung.
Der Haken bleibt trotzdem. Sanitizer sehen nur, was läuft. Ein Pfad ohne Test bleibt ungeprüft, und ThreadSanitizer meldet nur Rennen, die in genau diesem Durchlauf auftreten. Dazu kommt der Verschleiß der Disziplin: ein reinterpret_cast unter Termindruck, ein roher Zeiger über eine Modulgrenze, und die Zusage ist an dieser Stelle weg, ohne dass es irgendwo vermerkt wäre. In Rust braucht derselbe Schritt einen unsafe-Block, und der lässt sich im ganzen Projekt in einer Sekunde finden.
Die Werkzeugkette prägt den Alltag stärker als die Sprache
Auf der Rust-Seite steht eine Datei namens Cargo.toml mit den Abhängigkeiten, dazu cargo build, cargo test, cargo fmt, cargo clippy und cargo doc. Die Werkzeugkette selbst verwaltet rustup, die Pakete kommen aus einer einzigen Quelle. Wer heute in ein fremdes Rust-Projekt kommt, kann es meistens im ersten Anlauf bauen, weil es kaum etwas gibt, das jedes Projekt anders macht.
Auf der C++-Seite ist CMake der De-facto-Standard für die Baubeschreibung, aber die Abhängigkeiten kommen je nach Projekt aus den Systempaketen, aus vcpkg, aus Conan oder als mitgelieferter Quelltext im Repository. Diese Vielfalt ist historisch begründet und lässt sich nicht wegdiskutieren, sie kostet aber bei jedem neuen Rechner, jedem neuen Kollegen und jedem Wechsel der Zielplattform Zeit.
Die Kehrseite der einen Quelle gehört in dieselbe Abwägung. Ein Rust-Projekt zieht über die Abhängigkeitskette schnell mehrere hundert kleine Pakete herein, und cargo tree zeigt dir das ungeschönt. Diese Kette zu prüfen ist Arbeit. Cargo audit gleicht sie gegen die RustSec-Datenbank ab, und wer in einem regulierten Umfeld arbeitet, braucht darüber hinaus eine Regel, welche Pakete überhaupt hereindürfen. In der C++-Welt ist die Abhängigkeitsliste kürzer und die einzelne Bibliothek größer, was die Prüfung anders, aber nicht automatisch leichter macht.
Wo das Ökosystem tatsächlich dünner ist
Gut versorgt bist du bei allem, was mit Netzwerk, Serialisierung, Kryptografie, Parsern, Kommandozeilenwerkzeugen und Datenbankzugriff zu tun hat. Diese Bibliotheken sind ausgereift, breit eingesetzt und werden gepflegt. Wenn dein Bauteil in diese Richtung fällt, gibt es an der Ökosystem-Frage nichts zu diskutieren.
Dünner wird es bei Oberflächen, wo es nichts gibt, das den Funktionsumfang und die kommerzielle Unterstützung von Qt erreicht. Bei Numerik existieren Bindungen an BLAS und LAPACK sowie eigene Bibliotheken, die Bequemlichkeit und das Umfeld von Eigen sind aber nicht da. Bei Bildverarbeitung führt der Weg meistens über eine Bindung an OpenCV. Und in der Automatisierungstechnik liefern Hersteller ihre SDKs für Feldbus, Kameras und Antriebe als C- oder C++-Bibliothek mit einer Header-Datei. Aufrufen kannst du das, jeder Aufruf sitzt dann aber in einem unsafe-Block, du schreibst die Umhüllung selbst, und für alle Zusicherungen, die die C-Schnittstelle nur dokumentiert, haftest du ab da selbst.
Die Prüfung vor der Entscheidung ist schnell erledigt. Nimm die fünf wichtigsten Abhängigkeiten, such jede auf crates.io und sieh dir drei Dinge an: wie oft sie geladen wird, wann die letzte Veröffentlichung war und wie viele Leute daran arbeiten. Ein Paket mit einer einzigen betreuenden Person und der letzten Veröffentlichung vor drei Jahren ist ein anderes Risiko als eine Boost-Bibliothek, und dieser Unterschied gehört in die Vorlage und nicht in eine Fußnote.
Wann C++ die richtige Wahl bleibt
Wenn das Produkt an einem C++-Framework hängt, das die Architektur trägt, ist die Frage entschieden. Bei Qt, Unreal oder ROS wechselst du nicht die Sprache, sondern die Anwendung, und das ist ein anderes Vorhaben mit einer anderen Begründung. Dasselbe gilt, wenn ein Hersteller-SDK die Schnittstelle zur Hardware bildet und ohne Alternative ist.
Wenn die Codebasis in der Pflege ist und nur noch Fehlerbehebungen bekommt, zahlt sich die Ausbildungsinvestition nicht zurück. Die Rechnung ist einfach: Der Aufwand fällt einmal an, der Nutzen entsteht pro geschriebener Zeile, und wenn kaum noch Zeilen dazukommen, bleibt nur der Aufwand. Genauso, wenn in den nächsten zwölf Monaten Termine stehen, die keinen Puffer für eine Lernkurve haben.
Und wenn ihr sicherheitsgerichtet nach ISO 26262 oder IEC 61508 entwickelt, sind qualifizierte C++-Compiler seit Jahren etabliert, samt Erfahrung bei den Prüfstellen. Für Rust gibt es inzwischen ebenfalls eine qualifizierte Werkzeugkette, der Kreis der Anbieter ist aber deutlich kleiner, und die Erfahrung im eigenen Haus und beim Prüfer fehlt oft noch. Das ist kein Ausschlusskriterium, aber ein Posten, den du früh mit dem Qualitätswesen klärst und nicht erst kurz vor der Abnahme.
Dazu passende Kurse
Wenn diese Abwägung an einem eigenen Bauteil stattfinden soll statt an einem Beispiel aus dem Buch, sind Rust-Kurse für Entwickler aus der C++-Welt der kürzere Weg.
Fällt die Entscheidung gegen den Wechsel, ist derselbe Aufwand im vorhandenen Werkzeugkasten besser aufgehoben, und dafür gibt es Kurse zu sicherer Programmierung in C und C++ .
Wie sicher bist du beim Thema wirklich?
Lesen fühlt sich schnell nach Können an. Ein kurzer Test zeigt dir, was davon schon sitzt und wo sich ein Kurs lohnt. Kostenlos, ohne Anmeldung, mit einer Erklärung zu jeder Antwort.
Wo du genau das übst
Sehr angenehmes, gut vorbereitetes Seminar, kann ich nur empfehlen.
Häufige Fragen
Ist Rust schneller als C++?
Müssen wir dafür alles neu schreiben?
Was ist unsafe und wie schlimm ist das?
Ist Rust im industriellen Umfeld überhaupt angekommen?
Deine Ansprechpartner
Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.
Yves Hoppe
Weiterbildung & Beratung
Hilft dir, aus dem Rust-Programm den passenden Kurs für deinen Stand zu finden.
Norbert Jansen
Beratung & Inhouse
Plant mit dir Inhouse-Trainings, die auf eure Abläufe und euren Datenbestand zugeschnitten sind.
Die Entscheidung an eigenem Code prüfen
Bei cmt gehst du Rust mit Leuten durch, die aus derselben C++-Welt kommen, und siehst an einem Bauteil aus deinem Umfeld, wo der Borrow-Checker dir Arbeit abnimmt und wo er dich nur ausbremst.