Oh oui, c'est utilisé. Je travaille dans le domaine du traitement de paquets en réseau. Je suis allé dans deux sociétés différentes où nous traitons des paquets de réseau. Nous travaillons donc au niveau Ethernet ou IP, et non au-dessus de TCP.
Fait intéressant, dans les deux sociétés, C a été choisi plutôt que C ++. Dans l’une des sociétés, l’un des deux produits était construit sur le noyau Linux, alors que l’autre était construit dans l’espace utilisateur Linux. Le produit du noyau utilisé évidemment en C, le noyau Linux étant programmé en C, ils ont également choisi d'utiliser le C pour le produit en espace utilisateur. Les deux produits ont été développés à partir de l’an 2000 environ (le produit du noyau un peu avant 2000 et le produit de l’espace utilisateur un peu après 2000).
Dans l'entreprise où je suis allé après cela, le produit a été construit en C, pas en C ++. Il s’agit en réalité d’une poursuite du projet du milieu des années 90, bien qu’étant donné les exigences récentes en matière d’amélioration des performances, il a été décidé que tout serait réécrit. Nous avions une option pour sélectionner C ++ en raison de cette réécriture, mais nous ne l'avons pas fait.
Dans le domaine du traitement de paquets en réseau, les performances comptent beaucoup. Je souhaite donc implémenter ma propre table de hachage ayant des performances supérieures à celles des tables de hachage existantes. Moi, et non l'auteur de la table de hachage, je suis celui qui sélectionne la fonction de hachage à utiliser. Peut-être que je veux la performance et aller pour MurMurHash3 . Peut-être que je veux la sécurité et aller pour SipHash . Les allocateurs de mémoire sont évidemment personnalisés. En fait, toutes les structures de données importantes que nous utilisons ont été implémentées sur mesure pour des performances optimales.
Bien que rien n'empêche d'utiliser le C ++, c'est généralement une mauvaise idée. Une seule exception levée par paquet laissera tomber le taux de traitement des paquets à des niveaux inacceptables! Nous ne pouvons donc pas utiliser les exceptions de C ++. Bien trop lent. Nous utilisons déjà un type de code C orienté objet en implémentant des structures de données en tant que structures, puis en implémentant des fonctions opérant sur ces structures. C ++ permettrait d’avoir des fonctions virtuelles, mais les appels de fonction virtuels tueraient les performances s’ils étaient utilisés partout. Il est donc préférable d’être explicite et d’avoir un pointeur de fonction si des appels de fonction virtuels sont nécessaires.
C ++ fera beaucoup de choses derrière votre dos: allocation de mémoire, etc. Par contre, en C, cela n'arrive pas d'habitude. Vous pouvez écrire une fonction qui alloue de la mémoire, mais il ressort généralement de l'interface de la fonction que l'allocation est en cours.
Pour illustrer le type de micro-optimisation que vous pouvez effectuer lors de la programmation en C, consultez la macro container_of du noyau Linux. Bien sûr, vous pouvez utiliser container_of dans le code C ++, mais qui fait cela? Je veux dire, cela est tout à fait acceptable dans la plupart des programmes C, mais les programmeurs C ++ typiques proposeraient immédiatement autre chose, telle qu'une liste chaînée qui alloue les nœuds de liaison en blocs séparés. Nous ne le voulons pas car chaque bloc de mémoire alloué est mauvais pour la performance.
Peut-être que la seule chose qui nous serait bénéfique en C ++ est que C ++ autorise la métaprogrammation des modèles, ce qui signifie que vous pouvez parfois éviter les appels de fonctions virtuelles tout en conservant un paramètre de fonction et permettre au compilateur de mettre les fonctions en ligne. Cependant, la métaprogrammation des modèles est compliquée et nous avons réussi à répondre à toutes les exigences en C, de sorte que les avantages de cette fonctionnalité en C ++ ne sont pas si critiques.
Dans l'une des sociétés, nous avions un langage compilé personnalisé dans lequel une partie des fonctionnalités était implémentée. Devinez quel était le langage cible du compilateur? Assemblée? Non, nous devions prendre en charge les architectures 32 bits et 64 bits. C ++? Vous plaisantez sûrement. Évidemment, c'était C avec goto calculé par GCC . Ainsi, le langage personnalisé a été compilé en C (ou en fait la variante gcc de C qui prenait en charge la fonction goto calculée), et le compilateur C a produit