Oh ja, es wird benutzt. Ich arbeite auf dem Gebiet der Netzwerkpaketverarbeitung. Ich war in zwei verschiedenen Unternehmen, in denen wir Netzwerkpakete verarbeiten. Wir arbeiten also auf der Ethernet- oder IP-Ebene, nicht auf der Ebene über TCP.
Interessanterweise wurde in beiden Unternehmen C gegenüber C ++ ausgewählt. In einem der Unternehmen wurde eines der beiden Produkte auf dem Linux-Kernel erstellt, während das andere Produkt im Linux-Anwenderbereich erstellt wurde. Das Kernel-Produkt, das offensichtlich C als Linux-Kernel verwendete, ist in C programmiert, aber sie entschieden sich dafür, C auch für das Userspace-Produkt zu verwenden. Beide Produkte wurden ab etwa 2000 entwickelt (das Kernel-Produkt etwas vor 2000 und das Userspace-Produkt etwas nach 2000).
In der Firma, in die ich danach gegangen bin, wurde das Produkt auf C gebaut, nicht auf C ++. Tatsächlich handelt es sich um eine Fortsetzung eines Projekts aus der Mitte der neunziger Jahre, obwohl aufgrund der jüngsten Leistungsverbesserungsanforderungen beschlossen wurde, im Wesentlichen alles neu zu schreiben. Aufgrund dieses Umschreibens hatten wir die Option, C ++ auszuwählen, taten dies jedoch nicht.
Im Bereich der Netzwerkpaketverarbeitung spielt die Leistung eine große Rolle. Daher möchte ich meine eigene Hash-Tabelle implementieren, die eine höhere Leistung als vorhandene Hash-Tabellen aufweist. Ich, nicht der Autor der Hash-Tabelle, bin derjenige, der auswählt, welche Hash-Funktion verwendet werden soll. Vielleicht möchte ich Leistung und für MurMurHash3 gehen . Vielleicht will ich Sicherheit und greife zu SipHash . Speicherzuordnungen sind offensichtlich benutzerdefiniert. Tatsächlich wurden alle wichtigen Datenstrukturen, die wir verwenden, für eine höchstmögliche Leistung kundenspezifisch implementiert.
Es gibt zwar nichts, was die Verwendung von C ++ verhindern würde, aber es ist normalerweise eine schlechte Idee. Eine einzelne ausgelöste Ausnahme pro Paket senkt die Paketverarbeitungsrate auf nicht akzeptable Werte! Daher können wir die Ausnahmen von C ++ nicht verwenden. Viel zu langsam. Wir verwenden bereits eine Art objektorientierten C-Code, indem wir Datenstrukturen als Strukturen implementieren und dann Funktionen implementieren, die mit diesen Strukturen arbeiten. C ++ würde virtuelle Funktionen erlauben, aber virtuelle Funktionsaufrufe würden die Leistung beeinträchtigen, wenn sie überall verwendet würden. Es ist also besser, explizit zu sein und einen Funktionszeiger zu haben, wenn virtuelle Funktionsaufrufe benötigt werden.
C ++ erledigt eine Menge Dinge hinter Ihrem Rücken: Speicherzuweisung usw. In C dagegen passiert das normalerweise nicht. Sie können eine Funktion schreiben, die Speicher zuweist. In der Regel wird jedoch anhand der Schnittstelle der Funktion deutlich, dass die Zuweisung erfolgt.
Als Beispiel für die Art von Mikrooptimierungen, die Sie beim Programmieren in C vornehmen können, sehen Sie sich das Makro container_of im Linux-Kernel an. Sicher, Sie könnten container_of in C ++ benutzen, aber wer macht das? Ich meine, es ist in den meisten C-Programmen völlig akzeptabel, aber typische C ++ - Programmierer würden sofort etwas anderes vorschlagen, beispielsweise eine verknüpfte Liste, die die Verknüpfungsknoten als separate Blöcke zuordnet. Wir wollen das nicht, weil jeder zugewiesene Speicherblock schlecht für die Leistung ist.
Vielleicht ist das Einzige, was uns in C ++ zugute kommt, dass C ++ die Metaprogrammierung von Vorlagen ermöglicht. Dies bedeutet, dass Sie manchmal virtuelle Funktionsaufrufe vermeiden können, während Sie noch einen Funktionsparameter haben, und dass der Compiler die Funktionen einbinden kann. Die Metaprogrammierung von Vorlagen ist jedoch kompliziert, und wir haben es geschafft, alle Anforderungen in C zu erfüllen. Daher ist der Nutzen dieser Funktion in C ++ nicht so kritisch.
In einem der Unternehmen hatten wir tatsächlich eine benutzerdefinierte kompilierte Sprache, in der ein Teil der Funktionen implementiert war. Ratet mal, welche Zielsprache der Compiler hatte? Versammlung? Nein, wir mussten sowohl 32-Bit- als auch 64-Bit-Architekturen unterstützen. C ++? Sicher scherzen Sie. Offensichtlich war es C mit GCCs berechnetem goto . Daher wurde die benutzerdefinierte Sprache in C kompiliert (oder tatsächlich in die gcc-Variante von C, die computed goto unterstützt), und der C-Compiler erstellte eine Assembly.