French

LinuxFr.org Se connecter Faut‐il continuer à apprendre le C++ ? Derniers commentaires Étiquettes (tags) populaires Sites amis À propos de LinuxFr.org

  • Accueil
  • Article
  • LinuxFr.org Se connecter Faut‐il continuer à apprendre le C++ ? Derniers commentaires Étiquettes (tags) populaires Sites amis À propos de LinuxFr.org
LinuxFr.org Se connecter Faut‐il continuer à apprendre le C++ ? Derniers commentaires Étiquettes (tags) populaires Sites amis À propos de LinuxFr.org
Images
  • Par electronics-phone
  • 473 Vues

Le C++ est un langage qui a vu ses spécifications s’amonceler et se stratifier au cours des années. Il est encore très utilisé. Mais face à des concurrents comme Rust ou Go, quelle est sa place dans un environnement qui évolue ?

Cette dépêche qui a nécessité beaucoup de discussions, aura, vous le verrez, une forme un peu particulière.

  • La gestion de dépendance, la portabilité, le construction et la reproductibilité
  • Note aux lecteurs‐commentateurs
  • Origine de cette dépêche

    La dépêche C++17, genèse d’une version mineure a reçu 227 commentaires représentant un volume dix fois supérieur à la dépêche elle‐même. Et ces commentaires, très souvent bien écrits, nourrissent des trolls bien velus !

    L’idée de créer cette dépêche vient de deux constats :

    1. l’énergie dépensée et les nombreuses heures consacrées à rédiger ces 227 commentaires est phénoménale ;
    2. en revanche, la lecture de tous ces commentaires est laborieuse.

    Avec le recul, nous aurions pu concentrer tout cet investissement dans une dépêche collaborative du style « Aujourd’hui, est‐il pertinent de choisir le C++ pour une nouvelle application ? », afin de structurer et consolider tous les arguments dispersés au fil des commentaires.

    Objectif de cette dépêche

    Cette dépêche propose un sujet bien plus large : « Faut‐il continuer à apprendre le C++ ? ». Et de nombreux commentaires de qualité de la dépêche C++17, genèse d’une version mineure méritent d’être copiés, améliorés ou fusionnés ici. Malheureusement, ceux‐ci sont rarement sous licence compatible CC-BY-SA 4.0.

    Faire un article synthétique sur cette question n’est pas simple. En effet, le choix d’un langage pour un projet dépend énormément du contexte, en particulier le domaine d’application et l’environnement technique existant. Dans les discussions sur le choix d’un langage, certains avanceront des critères, mais ceux‐ci seront considérés par d’autres comme non pertinents.

    Même des critères « historiques » du C++ ne sont plus des arguments suffisants dans de nombreux projets. Par exemple, le C++ est souvent évoqué pour ses performances lorsque l’on veut créer un jeu vidéo. Mais de nos jours, avec la puissance disponible sur le moindre appareil et la qualité des moteurs de jeux, il n’est plus pertinent que tous ceux qui veulent travailler dans les jeux vidéo apprennent le C++.

    De même, si l’on prend un domaine dans lequel le C++ est généralement déconseillé, comme le développement Web. Et, cependant, de très grosses entreprises Web comme Google ou Facebook utilisent le C++.

    Il convient donc de revenir dans un premier temps sur les critères à prendre en compte dans le choix d’un langage, puis de voir les qualités et défauts du C++ sur ces critères.

    Dialogue sur divers aspects des enjeux brulants de C++ en 2018

    La normalisation, un processus trop lent ? Et quid de la nouvelle norme ISO vs mise à jour d’un logiciel (compilo, VM, etc.).

    gbdivers : Standard vs lib ? Pourquoi ne pas mettre toutes les fonctionnalités dans le standard. Exemple de regex, network, Unicode.

    gbdivers : Les nouveaux langages sont‐ils meilleurs que les anciens langages ? De grands débats apparaissent : const vs mutable, ref vs copie, explicit vs implicit.

    gbdivers : Peut‐on envisager de casser la rétrocompatibilité ? L’exemple du Python 2 vs Python 3 montre l’étendue des problèmes que cela implique…

    gbdivers : Complexe ? Oh oui ! Multiplication des syntaxes, syntaxes pas forcément intuitives.

    gbdivers : Passage complexe entre langages.

    gbdivers : L’apprentissage du C++ est réputé difficile…

    gbdivers : Conclusion : est‐ce que le C++ est fini ? Non !

    Le C++ en bref

    Le C++ est un vieux langage (bientôt 40 ans) hérité du langage C avec lequel il entretient une compatibilité.

    De tout ce long historique, le C++ a évolué du mieux possible entre paradigmes de programmation et nouveaux besoins. Au final, sa syntaxe évolue lentement, est complexe, bourrée de subtilités et lente à compiler.

    Mais c’est aussi un langage permettant des optimisations de folie (costless abstraction). Le C++ est utilisé au quotidien, ne serait‐ce que la plupart des environnements graphiques et des navigateurs Web (pour flâner sur LinuxFr.org). Et le C++ continuera pour encore de nombreuses années à être utilisé en production, notamment pour les applications critiques.

    Le C++ n’est pas mourant. Au contraire, le C++ connait un vif intérêt depuis C++11.De plus en plus de personnes s’investissent à améliorer davantage ce langage, comme sur la vitesse de compilation qui devrait être grandement améliorée avec C++20.

    LinuxFr.org Se connecter Faut‐il continuer à apprendre le C++ ? Derniers commentaires Étiquettes (tags) populaires Sites amis À propos de LinuxFr.org

    Alors, faut‐il tout effacer et recommencer un nouveau langage qui, par design, prend en compte les contraintes de concurrence (multicœur, NUMA) et de montée en charge (scalability) ? Des langages de programmation tentent d’obtenir des performances similaires avec une syntaxe expressive et concise.

    La puissance du C++

    Les points positifs qui démarquent le C++ sont sa programmation générique et sa méta‐programmation qui permettent d’avoir des abstractions sans pénalité de performance. Mais aussi les possibilités de libération déterministe et implicite de n’importe quel type de ressource au travers du RAII, si on le compare au C — les autres langages à exceptions disposent d’un ramasse‐miettes (garbage collector) et suivent le dispose pattern pour les autres ressources, voire offrent des facilités équivalentes au RAII (try‐with‐resources en Java 7, using en C#, etc.). Certains estiment que si l’on ne profite pas de ces fonctionnalités, mieux vaut utiliser un autre langage.

    Les alternatives

    Parmi ces langages, en excluant ceux qui ne sont qu’interprétés et ceux qui utilisent un ramasse‐miettes, les seuls qui pourraient remplacer C++ à performances égales sont donc : C, Rust et D.

    Critères pour adopter un nouveau langage

    Mais pour qu’un langage soit adopté plusieurs ingrédients sont nécessaires :

    Sur ce terrain, le C++ est bien doté avec de très nombreux outils, bibliothèques et communautés.

    Popularité du C++

    Et toi, chère lectrice, cher lecteur, penses‐tu que les nouvelles fonctionnalités du C++ ne font que compliquer inutilement le langage le plus complexe que l’humanité ait inventé ?Ou, au contraire, es‐tu persuadé·e que, grâce à ces évolutions, le C++ va progresser dans le classement du TIOBE Index et garder loin derrière des prétendants comme D, Dart, Nim, Rust ou Pony ?

    Autres sources :

    Questions

    Go

    Go a été créé par Google parce que la compilation C++ devenait rédhibitoire pour ses applications serveur.

    C++ a été initialement créé comme une extension du C, gardant la compatibilité avec lui, et non un pur langage objet. Il y a donc un mélange entre objets et types primitifs (comme dans java). Toutefois, contrairement à Java ou C#, C++ ne fait pas de différences fondamentales entre les types primitifs et les objets définis par l’utilisateur : c’est au programmeur de décider si les types sont copiables, l’usage des références est explicite, l’allocation sur la pile est possible.

    Certaines briques « de base », telles que les conteneurs ou les string, sont toutefois arrivées tardivement dans la spécification, ou de manière incomplète. Ainsi, beaucoup de bibliothèques réinventent la roue, ce qui peut mener à des difficultés ou un surcoût (conversions multiples) dans l’interopérabilité entre bibliothèques.

    Le compilateur permet de faire de la vraie métaprogrammation. Et c’est réellement utilisé. La métaprogrammation en C++ repose sur un modèle de typage structurel.

    En revanche, il n’y a pratiquement aucune aide à la gestion d’erreurs, bien que C++11 ait introduit static_assert. Les messages d’erreurs liés à la métaprogrammation sont souvent particulièrement cryptiques et demandent un certain degré d’habitude ou d’expertise pour être compris, et un degré encore supérieur pour savoir écrire des bibliothèques fortement génériques provoquant des messages d’erreurs intelligibles. Voir à ce sujet la présentation de Roland Block donnée lors de la CppCon 2015 : Pruning Error Messages From Your C++ Template Code [diapos]. À noter toutefois que les progrès récents du côté des compilateurs, tels que g++ ou Clang++, font que les messages d’erreurs sont un peu moins longs qu’avant.

    La gestion de la mémoire, et des ressources en général, en C++ est laissée à la charge du développeur. Cela a pendant longtemps abouti à la multiplication des problèmes tels que les fuites mémoires ou l’utilisation après libération, qui se manifestent aujourd’hui en autant de failles de sécurité. Toutefois, C++ fournit maintenant des outils intégrés à la bibliothèque standard, qui suivent le principe de RAII (Ressource Acquisition Is Initialization) pour gérer finement l’utilisation des ressources. Ce principe a été repris et généralisé dans le langage Rust (créé par Mozilla), qui veut se poser en alternative, mais reste aujourd’hui inférieur en termes d’écosystème (SIMD, multicœur / OpenMP, toolkit graphique façon Qt).

    D’un autre côté, si C++ trouve un moyen de détecter les vieilles constructions à éviter, que les types somme et le filtrage de type par motif (type pattern matching) est ajouté, que les pointeurs soient vus comme des types somme avec détection des « appels sur NULL » à la compilation, si des conteneurs sont introduits avec des interfaces fold/map/reduce pour réduire les erreurs off‐by‐one lors des parcours, si la compilation est plus rapide (peut‐être avec une gestion multi‐fichier du compilateur), si le modèle mémoire devient plus précis pour gérer les alignements mémoire, l’appartenance des objets en mémoire pour chaque fil d’exécution, et pour un éventuel ramasse‐miettes, C++ est là pour longtemps.

    Les spécifications

    Tiré du commentaire : https://linuxfr.org/news/c-17-genese-d-une-version-mineure#comment-1676200.

    La volonté de compatibilité des différentes versions de la norme pousse le comité de standardisation à ajouter des parties plutôt qu’à les remplacer. Cela pose plusieurs problèmes :

    En outre, le comité de normalisation est fermé. Même si le langage est ouvert (son implémentation), les spécifications sont payantes et soumises à des droits. Une aberration qui entraîne parfois des soupçons de corruption ou du moins une volonté d’entretenir une complexité spéciale pour justifier des experts. Ces critiques sont toutefois largement injustifiées, les brouillons des spécifications (quasiment identiques à la version finale) étant en accès libre, et le comité de normalisation s’étant énormément ouvert à la communauté C++ depuis le début des années 2010.

    La bibliothèque standard pas homogène

    Tiré du commentaire : https://linuxfr.org/news/c-17-genese-d-une-version-mineure#comment-1676200.

    La bibliothèque standard est très poussée pour des domaines assez pointus (comme les mathématiques), mais ne propose rien pour des usages très courants comme le multitâche qui est, lui, géré nativement par Rust.

    Des problèmes quotidiens semblent compliqués

    Tiré du commentaire : https://linuxfr.org/news/c-17-genese-d-une-version-mineure#comment-1676523.

    Des problèmes tout à fait quotidiens (comme le fait de n’inclure qu’une seule fois chaque fichier à la compilation) n’ont pas de solution triviale. Chaque développeur ou chaque projet gère donc cela à sa façon avec potentiellement des erreurs et sans capitalisation au sein de la communauté C++.

    La gestion de dépendance, la portabilité, le construction et la reproductibilité

    N. D. M. : Paragraphe à travailler, je jette des idées en vrac

    La gestion de dépendances en C++ est complexe. il faut pouvoir compiler un logiciel dans un contexte reproductible, qui, dans le meilleur des cas :

    Ce type de problème est souvent géré dans d’autre langages par des outils de gestion de dépendances, comme en Python avec pip, Haskell avec Stack, etc. Ces outils permettent de construire son programme dans un environnement restreint en fournissant tout ou partie des garanties listées au‐dessus.

    À ma connaissance, il n’existe pas d’outil multi‐plate‐forme de ce type en C++. Ainsi, chaque bibliothèque vient avec sa propre méthode de compilation et d’installation non générique et l’empaquetage d’un programme revient souvent à faire soi‐même, à la main, la construction de toutes les dépendances dans un répertoire dédié du projet, ce qui devient fastidieux quand on cherche aussi à s’assurer des numéros de version des outils de compilation utilisées.

    Sous Windows, il n’y a rien de vraiment solide, chaque année voit son lot de gestionnaire de paquets, comme Chocolatey, mais rien de suffisamment robuste ou exhaustif permettant de choisir les versions exactes des bibliothèques et outils.

    Sous GNU/Linux, chaque distribution propose son gestionnaire de paquets, garantissant que les dépendances fonctionnent au sein du système. Cependant, si la version de bibliothèque fournie ne correspond pas à celle nécessaire au programme, on en revient à une gestion à la main.

    On peut aussi utiliser une technologie de conteneur léger comme Docker et installer une distribution GNU/Linux spécifique avec un ensemble de paquets choisis. Mais cette méthode pose le problème des performances. Or, une des raisons de l’utilisation de C++ étant les performances, on peut se retrouver bloqué [citation/link needed].

    Avantages du C++ sur les autres langages

    Le C++ a malgré tout des avantages que l’on ne retrouve dans aucun autre ou pratiquement :

  • les systèmes d’exploitation étant écrits en C/C++, il est le langage pour parler nativement au système et donc efficacement, profitant de ces avantages, de nombreuses bibliothèques système ou bas niveau sont aussi en C ou C++ ;
  • l’écosystème C++ est riche de nombreuses bibliothèques inévitables dans certains domaines ; par exemple, de nombreux formats de fichiers et utilitaires de l’industrie du cinéma, tel que OpenEXR, OpenFX, OpenColorIO, OpenImageIO, Alembic, OpenVDB, OpenEXRID, etc., sont fournis sous la forme de bibliothèques C++. Bien que des bibliothèques de liaison (bindings) vers d’autres langages existent, celles‐ci ne garantissent pas forcement une compatibilité parfaite, aussi bien en termes de fonctionnalités que de performances. Par exemple, un tableau dynamique C++ (std::vector) n’est pas forcement compatible au niveau binaire avec son équivalent Rust, imposant la création d’une interface.
  • Note aux lecteurs‐commentateurs

    Je donne des exemples de bibliothèques de cette industrie parce que c’est celle que je connais et c’est actuellement la seule raison qui justifie notre utilisation du C++. D’autre personnes sont invitées à ajouter des exemples venant d’autres industries. De façon amusante, on dit souvent que des langages comme Python servent à faire la glu sur les entrées d’un programme et que le cœur est écrit dans un langage plus « sérieux » type C++. Nous, nous aurions plutôt tendance à vouloir utiliser du Rust ou du Haskell pour le cœur et à utiliser C++ pour la glu et les entrées‐sorties. C’est un point de vue assez amusant et à contre‐courant des idées habituelles.

    Et c’est ce point sur les performances tout en étant relativement haut niveau qui fait du C++ un langage que l’on ne peut remplacer dans beaucoup de projets. Les seuls candidats sont des langages aussi très anciens et qui finalement ont moins évolué (Pascal, Fortran…).Bien souvent, on développe une application dans un langage de haut niveau (Python, PHP, Ruby ou autres). Puis vient un moment où, pour des raisons de performance, on doit réécrire les parties les plus sollicitées. Par exemple, dans notre société, on développe en PHP et awk. Et quand les charges serveurs augmentent, on réimplémente le cœur en C/C++ et on garde une couche Bash ou PHP au‐dessus. La raison pour laquelle on ne développe pas directement en C/C++, est que son développement et sa maintenance sont plus longs. En C/C++, un bogue peut survenir sur un détail difficile à identifier, là où le PHP, très tolérant, accepte les problèmes. Il y a aussi en C/C++ le risque de ne plus savoir quelle version exacte du code avait servi à compiler la précédente version et donc une difficulté à savoir si lors d’une mise à jour les dernières évolutions du code ne vont pas perturber le fonctionnement en place. Autrement dit, il est difficile de savoir entre deux exécutables quelles sont les modifications apportées.

    Le C++ fait aussi son apparition dans l’embarqué. Là où il n’y avait qu’assembleur et C, la suite logique pour des composants toujours plus complexes est le C++. D’abord à travers l’utilisation simple de classes, permettant une meilleure architecture soit par encapsulation, soit par héritage. Mais de plus en plus, on voit arriver des morceaux de la bibliothèque standard, au fur et à mesure que l’embarqué accepte l’allocation dynamique de mémoire.

    Une autre force du C++ est la base d’utilisateurs le connaissant, du fait de sa longévité — il date de 1983.