Y a-t-il une raison d'utiliser C ++ au lieu de C, Perl, Python, etc.? [fermé]


164

En tant que développeur Linux (côté serveur), je ne sais pas où et pourquoi devrais-je utiliser le C ++.

Quand je vise la performance, le premier et dernier choix est C.

Quand la "performance" n'est pas le problème principal, des langages de programmation tels que Perl et Python seraient un bon choix.

Presque toutes les applications open source que je connais dans ce domaine ont été écrites en C, Perl, Python, Script Bash, AWK ou même PHP, mais personne n’utilise le C ++.

Je ne parle pas d'autres domaines comme l'interface graphique ou les applications Web, je parle simplement de Linux, de la CLI et des démons.

Existe-t-il une raison satisfaisante d'utiliser C ++?


5
Je ne considère que C ++ à cause de STL.
dan_waterworth

46
Donc, quelque chose qui peut être fait en utilisant C, Perl et Python ensemble peut être fait en C ++ seulement. Et vous demandez pourquoi utiliser C ++?
Manoj R

36
«Quand je vais à la performance, le premier et dernier choix est C.» Ouais bien sûr: D Ceci est une affirmation non prouvée et trivialement fausse.
deadalnix

16
@deadalnix: Je ne dirais pas ça. C ++ a des règles complexes qui peuvent se retourner contre l'optimiseur, car il n'est pas autorisé à faire certaines choses. Et il est très facile d'entrer dans la peau de tueurs de performances invisibles. C'est assez axiomatique, et donc vrai: D Toujours dans la réalité, le code C ++ sera parfois plus rapide car vous utiliserez des algorithmes et des structures de données plus efficaces, et personne n'optimisera réellement le code C de toute façon. Ainsi, une fois correctement effectué, le langage C ++ est un C plus sûr et plus efficace. Vous devez donc choisir C ++ au lieu de C lorsqu'il n'y a pas de problème de compatibilité ou que le logiciel à disponibilité 100% n'est pas requis.
Coder

4
La meilleure raison, non prise en compte dans les réponses affichées, est directement liée à la question de OP. DEPENDANCIES !!!!, Ce n’est pas que votre système moyen manque de librairies c ++, mais un système embarqué n’en dispose peut-être pas. La seule façon d’obtenir votre programme dans chaque système est d’écrire votre programme en C standard. Tout le reste ne fait que débattre de la raison pour laquelle vous ne devriez pas, ou moins, représenter le C ++. Rien de tout cela ne explique pourquoi le C ++ n'est pas utilisé plus souvent, et quel que soit le mérite, la raison en est les dépendances .... O et aussi le fameux c ++ de Linus.
JM Becker le

Réponses:


308

Quand je vais à la performance, le premier et dernier choix est C.

Et c'est là que vous devriez sauvegarder. Maintenant, je ne peux pas du tout parler pour le développement de serveur. Peut-être n'y a-t-il aucune raison impérieuse de préférer le C ++ aux alternatives.

Mais en règle générale, la raison d'utiliser C ++ plutôt que d'autres langages est en effet la performance. La raison en est que le C ++ offre un moyen d’abstraction qui, contrairement à tous les autres langages que je connais, ne nécessite pas de temps de performance supplémentaire au moment de l’exécution.

Cela permet d’écrire un code très efficace qui a toujours un niveau d’abstraction très élevé.

Considérez les abstractions habituelles: les fonctions virtuelles, les pointeurs de fonction et l'idiome PIMPL. Tous ces éléments reposent sur une indirection résolue au moment de l'exécution par l'arithmétique de pointeur. En d'autres termes, cela entraîne un coût de performance (aussi petit soit-il).

C ++, en revanche, offre un mécanisme d'indirection qui n'entraîne aucun coût (performance): les modèles. (Cet avantage est payé avec un temps de compilation accru (parfois énormément).)

Prenons l'exemple d'une fonction de tri générique.

En C, la fonction qsortprend un pointeur de fonction qui implémente la logique selon laquelle les éléments sont ordonnés les uns par rapport aux autres. La Arrays.sortfonction de Java se décline en plusieurs variantes. l' un d'entre eux trie les objets arbitraires et nécessite un Comparatorêtre passé objet à ce que fonctionne comme le pointeur de la fonction C de qsort. Mais il existe plusieurs surcharges supplémentaires pour les types Java «natifs». Et chacun d’entre eux a sa propre copie de la sortméthode - une duplication de code horrible.

Java illustre ici une dichotomie générale: soit vous avez la duplication de code, soit vous induisez une surcharge d’exécution.

En C ++, la sortfonction fonctionne comme qsorten C, avec une différence minime mais fondamentale: le comparateur transmis à la fonction est un paramètre de modèle . Cela signifie que son appel peut être inline . Aucune indirection n'est nécessaire pour comparer deux objets. Dans une boucle serrée (comme c'est le cas ici), cela peut réellement faire une différence substantielle.

Sans surprise, la sortfonction C ++ surpasse les performances de C sortmême si l'algorithme sous-jacent est le même. Cela est particulièrement visible lorsque la logique de comparaison réelle est bon marché.

Maintenant, je ne dis pas que C ++ est a priori plus efficace que C (ou d’autres langages), ni qu’il offre a priori une abstraction plus élevée. Ce qu’elle offre, c’est une abstraction à la fois très élevée et incroyablement peu chère, de sorte que vous n’avez souvent pas besoin de choisir entre un code efficace et un code réutilisable.


16
J'en sais maintenant assez sur le C ++ pour savoir si vous êtes dans le mille ou si vous vous trompez. Mais vous voulez aussi ajouter que vous n’avez reçu qu’un seul vote négatif, alors détendez-vous. C'est l'Internet et les votes négatifs arrivent. Très bonne réponse si c'est techniquement valable!
Chris

46
pas de surcharge de performance au moment de l'exécution - ce n'est pas toujours vrai. Si vous regardez les implémentations vectorielles STL, vous verrez qu'elles ne tirent pas avantage de realloc () (ils ne peuvent pas à cause des pointeurs, histoire longue) alors que tous les langages de niveau supérieur que je connais peuvent utiliser et utilisent realloc ( ) dans le vecteur impl Ce n'est qu'un exemple parmi d'autres: ce n'est pas si évident et tout est en noir et blanc.
Mojuba

19
@Jaroslaw, @Steve: mais le même (= code ballotté, erreurs de cache d'instruction) est vrai pour le code optimisé manuellement qui est adapté à chaque type de données (voir les différentes Arrays.sortimplémentations de Java ). Seulement, vous perdez l'avantage de l'abstraction élevée. Ce n'est pas un inconvénient spécifique des modèles, mais un inconvénient de la duplication de code en général. De plus, cela n'a pas d'importance, car dans les boucles serrées, c'est toujours le même code qui est chargé.
Konrad Rudolph

18
@Jaroslaw: ce qui est amusant avec le cache d'instructions, c'est qu'il s'agit d'un cache . C'est-à-dire qu'il n'essaye pas de tout stocker , seulement du code utilisé récemment . Les modèles peuvent générer beaucoup de code similaire pour différents types (un vector.push_backpour vector<int>et un autre pour vector<float>, mais tout en travaillant avec un vector<int>, il y a peu de raisons pour lesquelles le vector<float>code serait dans le cache d'instructions. Je ne vois donc pas en quoi cela est vraiment important. L' instanciation de modèles individuels est hautement optimisée et généralement plus compacte que les implémentations génériques "attrape-tout"
jalf

29
@ Steve314: Ce que vous appelez "gonfler" est ce qui est fait manuellement pour C et Java. En C ++, cela peut être automatisé et les compilateurs peuvent être aussi intelligents que les vendeurs osent les faire pour éviter les pertes. Si je dois choisir entre être lent (comme en C) ou utiliser du code dupliqué (comme en Java), laisser le compilateur faire la duplication (et peut-être être intelligent à ce sujet) me semble plutôt bien, non?
sbi

166

Je vois beaucoup trop de programmeurs C qui détestent le C ++. Il m'a fallu un certain temps (années) pour comprendre lentement ce qui est bon et ce qui est mal à son sujet. Je pense que la meilleure façon de la formuler est la suivante:

Moins de code, pas de temps d’exécution, plus de sécurité.

Moins nous écrivons de code, mieux ce sera. Cela devient rapidement évident pour tous les ingénieurs qui visent l'excellence. Vous corrigez un bogue à un endroit, pas beaucoup - vous exprimez un algorithme une fois, et le réutilisez dans de nombreux endroits, etc. Les Grecs ont même un dicton remontant aux anciens Spartans: "dire quelque chose en moins de mots, de moyens que vous êtes sage à ce sujet ". Et le fait est que, utilisé correctement , le C ++ vous permet de vous exprimer avec beaucoup moins de code que le C, sans perdre de temps à la vitesse d'exécution, tout en étant plus sûr (c'est-à-dire, en capturant plus d'erreurs au moment de la compilation) que le C.

Voici un exemple simplifié de mon moteur de rendu : lors de l'interpolation de valeurs de pixels sur la ligne de balayage d'un triangle. Je dois partir d'une coordonnée X x1 et atteindre une coordonnée X x2 (de gauche à droite d'un triangle). Et à chaque étape, à chaque pixel que je passe, je dois interpoler des valeurs.

Lorsque j'interpole la lumière ambiante atteignant le pixel:

  typedef struct tagPixelDataAmbient {
      int x;
      float ambientLight;
  } PixelDataAmbient;

  ...
  // inner loop
  currentPixel.ambientLight += dv;

Lorsque j'interpole la couleur (appelée ombrage "Gouraud", où les champs "rouge", "vert" et "bleu" sont interpolés d'une valeur de pas à chaque pixel):

  typedef struct tagPixelDataGouraud {
      int x;
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  } PixelDataGouraud;

  ...
  // inner loop
  currentPixel.red += dred;
  currentPixel.green += dgreen;
  currentPixel.blue += dblue;

Lorsque je fais un ombrage "Phong", je n’interpole plus une intensité (ambientLight) ou une couleur (rouge / vert / bleu) - j’interpole un vecteur normal (nx, ny, nz) et à chaque étape, je dois -calculer l'équation d'éclairage en fonction du vecteur normal interpolé:

  typedef struct tagPixelDataPhong {
      int x;
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  } PixelDataPhong;

  ...
  // inner loop
  currentPixel.nX += dx;
  currentPixel.nY += dy;
  currentPixel.nZ += dz;

Maintenant, le premier instinct des programmeurs C serait "zut, écrit trois fonctions qui interpolent les valeurs, et les appelle en fonction du mode défini". Tout d’abord, cela signifie que j’ai un problème de type - avec quoi je travaille? Sont mes pixels PixelDataAmbient? PixelDataGouraud? PixelDataPhong? Oh, attendez, le programmeur C efficace dit: utilisez une union!

  typedef union tagSuperPixel {
      PixelDataAmbient a;
      PixelDataGouraud g;
      PixelDataPhong   p;
  } SuperPixel;

..et alors, vous avez une fonction ...

  RasterizeTriangleScanline(
      enum mode, // { ambient, gouraud, phong }
      SuperPixel left,
      SuperPixel right)
  {
      int i,j;
      if (mode == ambient) {
          // handle pixels as ambient...
          int steps = right.a.x - left.a.x;
          float dv = (right.a.ambientLight - left.a.ambientLight)/steps;
          float currentIntensity = left.a.ambientLight;
          for (i=left.a.x; i<right.a.x; i++) {
              WorkOnPixelAmbient(i, dv);
              currentIntensity+=dv;
          }
      } else if (mode == gouraud) {
          // handle pixels as gouraud...
          int steps = right.g.x - left.g.x;
          float dred = (right.g.red - left.g.red)/steps;
          float dgreen = (right.g.green - left.a.green)/steps;
          float dblue = (right.g.blue - left.g.blue)/steps;
          float currentRed = left.g.red;
          float currentGreen = left.g.green;
          float currentBlue = left.g.blue;
          for (j=left.g.x; i<right.g.x; j++) {
              WorkOnPixelGouraud(j, currentRed, currentBlue, currentGreen);
              currentRed+=dred;
              currentGreen+=dgreen;
              currentBlue+=dblue;
          }
...

Sentez-vous le chaos s'infiltrer?

Tout d’abord, il suffit d’une faute de frappe pour planter mon code, car le compilateur ne m’arrêtera jamais dans la section "Gouraud" de la fonction pour accéder réellement au fichier ".a". (ambiant) valeurs. Un bogue non détecté par le système de type C (c'est-à-dire lors de la compilation) désigne un bogue qui se manifeste au moment de l'exécution et qui nécessite un débogage. Avez-vous remarqué que je suis left.a.greenen train d' accéder au calcul de "dgreen"? Le compilateur ne vous l'a sûrement pas dit.

Ensuite, il y a de la répétition partout - la forboucle est là autant de fois qu'il y a de modes de rendu, nous continuons à faire "juste moins gauche divisé par étapes". Moche et sujet aux erreurs. Avez-vous remarqué que je compare en utilisant "i" dans la boucle de Gouraud, alors que j'aurais dû utiliser "j"? Le compilateur est à nouveau silencieux.

Qu'en est-il du if / else / ladder pour les modes? Et si j'ajoutais un nouveau mode de rendu, dans trois semaines? Est-ce que je me souviendrai de gérer le nouveau mode dans tous les "if mode ==" dans tout mon code?

Maintenant comparons la laideur ci-dessus, avec cet ensemble de structures C ++ et une fonction template:

  struct CommonPixelData {
      int x;
  };
  struct AmbientPixelData : CommonPixelData {
      float ambientLight;
  };
  struct GouraudPixelData : CommonPixelData {
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  };
  struct PhongPixelData : CommonPixelData {
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  };

  template <class PixelData>
  RasterizeTriangleScanline(
      PixelData left,
      PixelData right)
  {
      PixelData interpolated = left;
      PixelData step = right;
      step -= left;
      step /= int(right.x - left.x); // divide by pixel span
      for(int i=left.x; i<right.x; i++) {
          WorkOnPixel<PixelData>(interpolated);
          interpolated += step;
      }
  }

Maintenant, regarde ça. Nous ne faisons plus de soupe d'union: nous avons des types spécifiques pour chaque mode. Ils réutilisent leur substance commune (le champ "x") en héritant d'une classe de base ( CommonPixelData). Et le modèle fait au compilateur CRÉER (c’est-à-dire générer du code) les trois fonctions différentes que nous aurions nous-mêmes écrites en C, tout en étant très strictes concernant les types!

Notre boucle dans le modèle ne peut pas goof et accéder à des champs non valides - le compilateur aboyera si nous le faisons.

Le modèle effectue le travail commun (la boucle, augmentant chaque "étape"), et peut le faire d'une manière qui ne peut simplement PAS causer d'erreurs d'exécution. L'interpolation par type ( AmbientPixelData, GouraudPixelData, PhongPixelData) se fait avec la operator+=()que nous ajouterons dans les struct - qui dictent essentiellement la façon dont chaque type est interpolée.

Et voyez-vous ce que nous avons fait avec WorkOnPixel <T>? Nous voulons faire un travail différent par type? Nous appelons simplement une spécialisation de modèle:

void WorkOnPixel<AmbientPixelData>(AmbientPixelData& p)
{
    // use the p.ambientLight field
}


void WorkOnPixel<GouraudPixelData>(GouraudPixelData& p)
{
    // use the p.red/green/blue fields
}

C’est-à-dire que la fonction à appeler est déterminée en fonction du type. Au moment de la compilation!

Pour le reformuler à nouveau:

  1. nous minimisons le code (via le modèle), en réutilisant les parties communes,
  2. nous n'utilisons pas de hacks laids, nous gardons un système de types strict, afin que le compilateur puisse nous contrôler à tout moment.
  3. Et le meilleur de tous: rien de ce que nous avons fait n’a AUCUN impact sur l’exécution. Ce code fonctionnera JUSTE aussi rapidement que le code C équivalent. En fait, si le code C utilisait des pointeurs de fonction pour appeler les différentes WorkOnPixelversions, le code C ++ serait plus rapide que le code C, car le compilateur incorporerait la WorkOnPixelspécialisation de modèle spécifique au type. appel!

Moins de code, pas de temps d’exécution, plus de sécurité.

Cela signifie-t-il que C ++ est le berceau et le tout des langages? Bien sûr que non. Vous devez encore mesurer les compromis. Les personnes ignorantes utiliseront C ++ alors qu'elles auraient dû écrire un script Bash / Perl / Python. Les débutants en C ++ déclencheurs créeront des classes imbriquées profondes avec un héritage multiple virtuel avant que vous puissiez les arrêter et les envoyer. Ils utiliseront la méta-programmation Boost complexe avant de se rendre compte que cela n'est pas nécessaire. Ils utiliseront ENCORE char*, strcmpet les macros, au lieu de std::stringet des modèles.

Mais cela ne dit rien de plus que… regarde avec qui tu travailles. Il n'y a pas de langage pour vous protéger des utilisateurs incompétents (non, pas même Java).

Continuez à étudier et à utiliser le C ++ - mais évitez de sur-concevoir.


18
+1 pour "non, pas même Java" :)
Nathan Osman

53
+1 pour l'exemple. C'était un long post, mais la comparaison entre le code C et le code C ++ est impressionnante.
paercebal

Et ceci, mesdames et messieurs, est la raison pour laquelle Lex / Yacc existe. Même raisonnement, je n’ai jamais réalisé que des parties de c ++ tombaient dans la même philosophie de génération de code. Je devrai le regarder à nouveau de temps en temps.
Spencer Rathbun

2
J'ai écrit beaucoup de code de rendu 2D (il y a plus de dix ans) et j'ai rencontré ce problème lors du portage de C à C ++: comment définir une structure de pixels si votre ligne de balayage est composée de pixels de 1 bit (8 pixels) un octet)? Et quand votre ligne de balayage est composée d'octets R, V et B (3 octets par pixel)? Et quand vous avez trois tampons distincts pour R, G et B? Vous connaissez la réponse: le C ++ n’est d'aucune aide là-bas, et insister sur l'utilisation de modèles vous fera perdre de nombreuses optimisations d'espace et de temps
Walter Tross

Pourquoi utilisez-vous des modèles en C ++ pour cela? Votre méthode déclare un paramètre de la classe de base. Ainsi, de mon point de vue [programmeur C #], il semblerait que vous puissiez simplement passer d'instance de type dérivé à un paramètre de type base. Je ne connais pas le C ++, pourriez-vous expliquer s'il vous plait?
Vlad

79

RAII pour gagner bébé.

Sérieusement, la destruction déterministe en C ++ rend le code beaucoup plus clair et sécurisé, sans aucun frais supplémentaire.


20
« C ++: La seule sérieusement l' option déterministe Demandez à votre médecin à ce sujet aujourd'hui. ».
Kyle Strand

2
Suivi: Rust est maintenant un concurrent dans ce domaine. Voir un exemple RAII de base et une documentation sur les méthodes de destruction de Rust .
Kyle Strand

1
C sera aussi déterministe, mais il faudra plus de travail pour être sûr qu'il se produise lors de l'utilisation de la mémoire en malloc-ed
Baldrickk

1
@Baldrickk en C, vous devez écrire du code de nettoyage partout où vous utilisez une ressource. En C ++, vous l'écrivez une fois dans la définition de la ressource. C et Java souffrent tous deux de bogues "ressource utilisée après suppression" et "fuite de ressource", car le nettoyage n’est pas automatique . La mémoire n'est pas la seule ressource.
Caleth

70

Existe-t-il une raison satisfaisante pour utiliser le C ++?

  1. Modèles et la STL. Vous échangez un peu de temps de construction (et des messages d'erreur potentiellement incompréhensibles) contre de nombreux outils d'abstraction et de réduction du temps de travail utiles, sans impact sensible sur les performances d'exécution (bien que l'empreinte binaire puisse être un peu plus grande).

    Il faut un certain temps pour enrouler autour de votre tête (m'a pris quelques années avant qu'il a cliqué), mais une fois que vous le faites peut rendre la vie beaucoup plus simple.

  2. Le traitement de texte en C ++ est d’ ordre de grandeur moins douloureux qu’en C.


35
+1 pour le traitement de texte, ce que j'ai complètement oublié dans ma réponse.
Konrad Rudolph

8
Heh j'ai trouvé le traitement de texte particulièrement pénible comparé à, disons, Python ..
Nils

7
Boost est la seule raison pour laquelle j'utilise encore le C ++.
Ferruccio

33
@Nils: sur une échelle de 1 à peindre, le traitement de texte en C ++ est nettement pire que dans des langages plus modernes comme Python. C'est juste que le traitement de texte en C définit la douleur dans le cul. Si le choix est entre C et C ++ pour cette application particulière, C ++ gagne facilement.
John Bode

8
Je ne sais pas pourquoi les gens ont une telle difficulté avec des choses comme le traitement de texte en C / C ++. Utilisez simplement une bibliothèque ou écrivez la vôtre. Une fois que vous avez écrit les fonctions de bas niveau (douleur ponctuelle), vous gagnez des performances énormes, un code strict et une plus grande flexibilité. Oui, j'utiliserai Python pour les utilitaires de ligne de commande rapides / sales, mais pour le code de production sérieux, C / C ++.

41

Oui.

Si vous recherchez une efficacité exécutable, vous devez utiliser C ou C ++, je vais donc me concentrer sur cela.

Même avant que les modèles ne soient courants, je préférais utiliser C ++ plutôt que C pour les types de fichiers exécutables dont vous discutez dès le milieu des années 90 pour deux raisons très simples: le polymorphisme d'objet et RAII .

J'ai utilisé des objets C ++ polymorphes pour toutes sortes de choses intéressantes. Par exemple, je travaillais sur un système Linux intégré avec des superpositions de mémoire tampon sur les processeurs OMAP et XScale ARM. Les deux architectures matérielles ont des fonctionnalités de superposition différentes avec des API très différentes. J'ai utilisé une classe de base "Overlay" virtuelle commune pour exposer une vue idéalisée des incrustations, puis j'ai écrit les classes "OmapOverlay" et "XScaleOverlay" qui étaient instanciées de manière appropriée à l'exécution, en fonction de l'architecture sur laquelle le code était détecté.

Pour simplifier à l'extrême, RAII est l'idée que vous allouez des ressources connectées à un objet pendant le constructeur de l'objet, ou peut-être plus tard dans la vie de l'objet, et que les ressources sont libérées ou libérées dans le destructeur de l'objet. C'est vraiment bien en C ++, parce que les objets qui sont des variables automatiques sont détruits lorsqu'ils sortent de la portée. Pour quelqu'un qui est tout aussi compétent en C et C ++, il est beaucoup plus facile d'éviter les fuites de ressources et de mémoire en C ++. De plus, vous ne voyez pas beaucoup de code C ++ avec le mème C très courant d’une étiquette à la fin d’une fonction précédant un groupe d’appels vers free(), et divers gotodans le bloc fonctionnel qui saute là.

Je suis tout à fait conscient que vous pouvez faire toutes ces choses avec C: c'est beaucoup plus de travail, beaucoup plus de lignes de code et ce que vous avez comme résultat est beaucoup plus laid et souvent plus difficile à comprendre. Il existe un code de polymorphisme dans tous les éléments internes du serveur X et, mec, est-ce fugly et étrange et souvent difficile à retracer.

Je travaille également beaucoup avec les technologies GNOME telles que GTK + et Clutter, qui sont toutes écrites en C en utilisant le système GObject. GObject est comme le système d’objets C ++ avec la belle couverture enlevée et tous les éléments internes laids exposés, et nécessite généralement une demi-douzaine de lignes de code pour faire ce que ferait un appel de méthode C ++ sur une ligne. J'en écris actuellement ClutterActors, et bien que le calcul soit vraiment intéressant, je pense constamment: "Tout cela serait tellement plus succinct et compréhensible en C ++".

Je pense aussi souvent: "Si je écrivais ceci en C ++ au lieu de C, je resterais dans le salon en train de regarder MythBusters avec ma femme au lieu de rester dans mon bureau à 21 heures."


9
Je peux vraiment comprendre ce que vous dites ici, en particulier 1) le point concernant RAII et 2) la pensée "Vous savez, si j'écrivais cela en C ++ au lieu de C ...", je fais beaucoup de développement de systèmes embarqués Et même si l’équipe est plutôt une boutique de type "C" ou "C avec classes", j’essaie vraiment d’encourager RAII pour des tâches telles que la manipulation d’interruptions, les opérations de mutex et le traçage / enregistrement (en particulier des choses comme le basculement des E / S lignes). Et votre description des mémoires tampons polymorphes m'a rappelé mon utilisation des tampons de messages polymorphes dans un système distribué.
Radian

29

Le C ++ est à peu près aussi rapide que le C (certaines choses sont plus rapides, d'autres plus lentes), et il offre de meilleures abstractions et une meilleure organisation. Les classes fonctionnent de la même manière que les types primitifs, ce qui permet d’utiliser de grandes quantités de code sans que l’on garde à l’esprit. La surcharge des opérateurs et les modèles permettent d’écrire un code qui fonctionne mieux si les représentations de données changent. Les exceptions peuvent permettre une gestion plus facile des erreurs. Le compilateur peut être utilisé pour vérifier plus de choses au moment de la compilation.

Le prix que vous payez pour cela est une courbe d'apprentissage assez désagréable, et il est plus facile de s'y tromper que la plupart des autres langues que je connais bien.

Donc, je ne peux pas dire si cela vaudrait la peine de l’apprendre pour ce que vous faites maintenant. Vous pouvez certainement vous en tirer avec des combinaisons de Python ou de Perl et C, mais C ++ offre à la fois abstraction et performance dans un package difficile à utiliser.


13
Il n'y a pas de cas dans lequel C ++ est plus lent que C, car vous pouvez toujours utiliser la méthode C si elle est plus rapide (et cela vous importe).
Jack Aidley

1
@JackAidley - Sauf que C ++ ne prend pas en charge les paramètres de tableau restrictifs et statiques. Et sauf que l'utilisation du style C ++ à un endroit vous oblige à l'utiliser à d'autres endroits.
martinkunev

@martinkunev restrictest utilisé pour faire des exclusions de l' aliasing Optimisations, alors comment cela aide à rendre les choses plus vite ? et qu'est-ce qu'un "paramètre de tableau statique"? et comment le "style" affecte-t-il les performances?
underscore_d

1
@underscore_d restrict autorise les optimisations basées sur une garantie de non aliasing; Les paramètres de tableau statique permettent au compilateur de supposer qu'un argument de pointeur n'est pas NULL et que ce pointeur pointe vers au moins un nombre donné d'éléments. le mot "style" a plusieurs significations et sa mise hors contexte en change le sens - je parle de la façon dont, par exemple, les exceptions imposent l'utilisation de pointeurs intelligents.
martinkunev

1
@martinkunev Hmm, je me demande donc si un paramètre de tableau statique autorise une fonctionnalité différente d'un modèle C ++ utilisant un T (&arr)[n]ou std::array<T, n>- devra faire des recherches plus approfondies, car il n'y a pas beaucoup d'informations disponibles. Cela fait sens sur les pointeurs intelligents, certainement un bon exemple. Si vous codiez sur un pied d'égalité, nous n'utiliserions pas d'exceptions, ce qui évite les coûts potentiels. Cependant, je suppose que vous faites allusion à la manière dont, une fois que des bibliothèques tierces ont été prises en compte, beaucoup d'hypothèses Sont à risque.
underscore_d

27

Je considère le C ++ comme un langage des années 90, un langage d’une époque révolue.

À l'époque, il était gros parce qu'il offrait des constructions et des mécanismes de langage de niveau supérieur à un coût inférieur en termes de performances. C’était l’outil universel pour tout développer, des applications de carnet d’adresses aux logiciels avioniques, ce qui a inspiré l’engouement pour les OO. OOP a résolu la faim et le sida, et oui, je reproche au C ++ d’essayer de me laver le cerveau à la fin des années 1990, lorsque j’ai commencé à programmer que tout langage non-OO ne valait pas la peine d’être appris.

Maintenant que le matériel a beaucoup évolué et que de nouveaux langages modernes sont apparus, je ne vois pas le C ++ demeurer un choix pertinent pour la plupart des programmes d’application, à l’exception des logiciels intensifs en calcul nécessitant encore une certaine abstraction (jeux, simulations physiques, systèmes de CAO, etc.). ). Même ce dernier peut être évité si vous écrivez un moteur compact et modulaire en C et si vous avez une logique d’application de niveau supérieur déléguée à un langage de script soigné.

Si vous devez utiliser le métal correctement et sereinement, faites-le dans un langage moderne qui n'annonce pas l'encapsulation, alors que vous pouvez modifier librement chaque octet au moyen d'un pointeur.


11
Donc, ne modifiez pas les octets aléatoires en utilisant des pointeurs. Ce n'est pas si difficile à éviter, n'est-ce pas?
David Thornley

11
@Blagovest: Je suis d'accord avec vous sur la complexité de C ++ et je ne l'utiliserais jamais pour remplacer un langage orienté objet. Malgré sa complexité, il gagne toujours C pour moi en raison de ses nombreux avantages, énoncés dans différentes réponses (abstraction, gestion des ressources, traitement des chaînes, etc.). En fait, vous avez nommé quelques zones valides où le C ++ est toujours pertinent et de loin supérieur au C.
Konrad Rudolph

6
@ Blagovest: C'est pourquoi je reste en dehors des coins sombres. Il est plus facile de se faire agresser en C ++ que tout autre langage que je connais. En l'utilisant, je profite de RAII, d'une bien meilleure gestion des chaînes que C, des classes de modèles de type STL, des fonctionnalités OO et de nombreux autres avantages dont il dispose par rapport à C.
David Thornley

24
@ Blagovest: Non. Par exemple, ce que vous avez mentionné est insuffisant pour atteindre la norme RAII, et les classes de conteneur ont des fonctionnalités qui vont au-delà des simples structures de données conçues à la main. Si vous pensez que cela est possible, vous n’avez jamais bien appris le C ++.
David Thornley

5
@Jaroslaw Je ne vois pas pourquoi les machines multi-cœurs mettraient la POO dans la tombe. Si vous parlez de C ++, je pourrais voir d’où vous veniez. La POO est un concept fondamental dans de nombreux langages de programmation modernes, en particulier les langages de haut niveau. Même C peut être OO, si vous le programmez de cette façon. Ce n'est tout simplement pas aussi pratique que C ++ IMO.
vedosity

21

Selon Linus , non:

Lorsque j'ai examiné le code source de Git pour la première fois, deux choses me semblaient étranges: 1. Pure C par opposition à C ++. Aucune idée pourquoi. S'il vous plaît ne parlez pas de la portabilité, c'est BS.

VOUS êtes plein de conneries.

C ++ est un langage horrible. Cela est rendu encore plus horrible par le fait que beaucoup de programmeurs insatisfaisants l'utilisent, au point qu'il est beaucoup plus facile de générer une merde totale et totale avec. Très franchement, même si le choix de C ne faisait que garder les programmeurs C ++ à l'écart, ce serait en soi une énorme raison d'utiliser C.

En d'autres termes: le choix de C est le seul choix sensé. Je sais que Miles Bader a dit en plaisantant "de vous faire chier", mais c'est en réalité vrai. Je suis venu à la conclusion que tout programmeur qui préféreraient que le projet soit en C ++ sur C est probablement un programmeur que je vraiment me préfère pisser, de sorte qu'il ne vienne pas bousiller tout projet que je suis impliqué avec.

C ++ conduit à de très mauvais choix de conception. Vous commencez invariablement à utiliser les "belles" fonctionnalités de la bibliothèque du langage, telles que STL et Boost, ainsi que d’autres conneries qui peuvent vous "aider" à programmer, mais qui causent:

  • une quantité infinie de douleur quand ils ne fonctionnent pas (et quiconque me dit que STL et surtout Boost sont stables et portables est tellement rempli de BS que ce n'est même pas drôle)

  • Modèles de programmation abstraits inefficaces dans lesquels, deux ans plus tard, vous remarquerez qu'une abstraction n'était pas très efficace, mais maintenant tout votre code dépend de tous les modèles d'objet sympas qui l'entourent, et vous ne pouvez pas le réparer sans réécrire votre application.

En d'autres termes, le seul moyen de faire du C ++ portable de qualité, efficace et de niveau système et portable finit par se limiter à tout ce qui est fondamentalement disponible en C. Et limiter votre projet à C signifie que les gens ne se font pas avoir. Cela signifie également que beaucoup de programmeurs comprennent réellement les problèmes de bas niveau et ne bousillent pas les conneries de "modèles d'objet" idiots.

Donc, je suis désolé, mais pour quelque chose comme Git, où l'efficacité était un objectif primordial, les "avantages" du C ++ sont simplement une énorme erreur. Le fait que nous énervions également des personnes qui ne peuvent pas voir cela est simplement un gros avantage supplémentaire.

Si vous voulez un VCS écrit en C ++, jouez avec Monotone. Vraiment. Ils utilisent une "vraie base de données". Ils utilisent "de belles bibliothèques orientées objet". Ils utilisent "de belles abstractions C ++". Et franchement, à la suite de toutes ces décisions de conception qui paraissent si attrayantes pour certains membres du personnel de CS, le résultat final est un gâchis horrible et incontrôlable.

Mais je suis sûr que tu aimerais plus que ça.

      Linus

62
Je ne pense pas que Linus soit le type à utiliser pour les arguments. Ses coups de gueule sont horriblement subjectifs et immatures. Il a effectivement quelques points positifs, mais ils sont tellement enfouis (au-dessous des "conneries" que des conneries) qu'ils sont très difficiles à trouver.
Konrad Rudolph

19
Haha, c'était un bon rire. Je ne veux jamais rencontrer ce mec.
Felix Dombek

30
Linus me fait penser à un couvreur très talentueux qui n’a jamais accroché le placoplâtre, mais qui appelle ses pensées parce qu’elles utilisent des vis au lieu de clous.
Bob Murphy

8
Linus a raison, mais l'exprime trop durement pour être pris au sérieux.
Blagovest Buyukliev

39
Je suis d'accord avec @Daniel, s'il y a quelqu'un qui peut parler de repousser les limites du matériel, c'est John Carmack, créateur de Doom, de Quake et d'autres jeux et fondateur du logiciel Id. Il a écrit ceci à propos de c et c ++ sur un twitt il y a quelques mois: "IMO, un bon code C ++ vaut mieux qu'un bon code C, mais un mauvais C ++ peut être beaucoup, bien pire qu'un mauvais code C." twitter.com/#!/ID_AA_Carmack/status/26560399301
Onema

18

Je ne pense pas qu'il y ait une raison impérieuse d'utiliser le C ++. Si vous voulez faire de la programmation OO, vous pouvez utiliser Python à la place et écrire les parties qui nécessitent des performances rapides en C.

EDIT: Il existe d'autres langages qui interagissent bien avec C, donc si vous n'aimez pas Python, il existe des alternatives.


3
Qu'en est-il du développement intégré? Python n'est pas toujours disponible et la différence de vitesse entre le C ++ et le C ++ bien écrit est négligeable sur les périphériques ayant atteint un certain niveau de puissance de traitement. Bien sûr, je suppose qu'un compilateur C ++ ne serait pas toujours disponible non plus ...
James

6
@ James "bien écrit C ++"
voilà le piège

5
Je suis d'accord avec cette réponse, faites le plus haut niveau avec python, puisque vous l'écrivez quelque chose comme 3 fois plus rapide, profilez, puis libérez les goulets d'étranglement en les remplaçant par C / C ++. Il est redondant de dire «remplacez le goulot d'étranglement par du code C ++», car vous ne ferez pas un niveau élevé avec le code dont vous avez besoin pour être rapide, car il s'agira d'un code de bas niveau. Il y a une chose: je ne sais pas comment interfacer c ++ avec python: /. mais en terme de temps passé devant l'écran et d'efficacité, je pense que c'est la meilleure solution, car la plupart du code C ++ sera rapide pour rien!
jokoon

8
Allez travailler pour une grande société financière et construisez un système financier complexe dans une grande équipe distribuée en Python et voyez comme vous l'aimez. L'expérience vous apprendra: a) les avantages de la sécurité de type, b) les avantages des compilateurs permettant d'économiser vos fesses, c) du code LUDICROUS que Python autorise l'écriture par des noobs. Les gens disent qu'il est facile de se tirer dans le pied avec C ++ -> certaines choses en python peuvent fonctionner, mais être une folie limite. En ce moment, je préférerais tellement travailler en C ++ ...
MrFox

1
@suslik: Wow, je suis choqué que quiconque utilise Python pour ce type de système. Je suis d'accord avec vous à propos du mauvais code Noob python; J'en ai vu moi-même.
Larry Coleman

13

Y a-t-il une raison d'utiliser C ++? Certainement.

Certaines personnes pourraient simplement préférer utiliser C ++ à d'autres options. Demander s'il y a une raison d'utiliser le C ++ revient à demander pourquoi nous avons besoin de centaines de parfums de crème glacée. Tout le monde n'aime pas simplement rester avec Vanilla.

Si les développeurs sont déjà très compétents en C ++, la question qui leur est posée n'est peut-être pas "pourquoi l'utiliser?", Mais plutôt "pourquoi pas?". Il semble y avoir actuellement une tendance anti-C ++ à la mode dans SO, mais croyez-le ou non, tout le monde ne souscrit pas à cela. Certaines personnes peuvent simplement aimer le C ++ mieux que les autres langages.

C ++ doit-il être utilisé pour les applications? Bien sûr que non. Mais cette même question exacte peut également être posée pour toute autre langue. Il existe très très peu de cas dans lesquels une langue particulière doit être utilisée pour une application.


12

Je passe simplement du C au C ++, et je pense que le gain est considérable, même si vous n'avez pas besoin de modèles ni de POO.

  • Meilleure gestion de la mémoire
  • Système de type plus fort
  • Une meilleure bibliothèque standard
  • Espaces de noms
  • etc.

8

Je suis surpris que personne n'en ait encore parlé, mais le C ++ nous a présenté des références , qui résolvent presque tous les problèmes et les pièges des pointeurs:

void ModifyVar(int& var)
{
    var = 5;
}

int test = 4;
ModifyVar(test);

Au lieu de:

void ModifyVar(int * var)
{
    *var = 5;
}

int test = 4;
ModifyVar(&test);

Beaucoup plus sûr et facile aussi ... et sans les frais généraux liés à la transmission par valeur.


3
Aussi beaucoup moins flexible. Les références (style C ++) sont efficaces pour simplifier certaines constructions communes dans un langage qui comporte également des pointeurs, mais elles sont loin de remplacer les pointeurs, ce n'est même pas drôle. Et votre exemple n’est pas du tout un bon argument pour des références.
Ben Voigt

3
@Ben: Pouvez-vous alors expliquer pourquoi c'est un mauvais exemple?
Nathan Osman

6
@ George: Parce que rien n'a changé, si ce n'est que deux (les compte) caractères plus courts? Cela ne résout aucun problème, cela ne met en évidence aucun piège, cela ne fait même rien de cool, comme de prolonger la durée de vie d'une variable temporaire (pour laquelle les références sont bonnes).
Ben Voigt

@ Ben: Vous oubliez quelque chose - la référence est toujours valide. Les pointeurs peuvent indiquer n'importe quoi (y compris NULL) pouvant entraîner toutes sortes d'erreurs de mémoire si les choses ne sont pas bien faites. Les références ne peuvent jamais être NULL et l'adresse qu'elles désignent ne peut jamais être modifiée.
Nathan Osman

5
@ George: "la référence est toujours valide" est totalement faux. Je donnerai un exemple si vous en avez besoin, mais j'espère que vous êtes suffisamment expert pour être déjà au courant. Et je ne parle pas non plus de former une référence invalide en utilisant un pointeur invalide. Les fonctions qui utilisent des pointeurs nécessitent une documentation indiquant les conditions préalables des arguments. Mais pratiquement, toutes les fonctions ont besoin de ce niveau de documentation, il est donc absurde d'appeler cela une frappe contre des pointeurs.
Ben Voigt

5

Le où et pourquoi vont généralement être:

  • familiarité
  • fonctionnalités linguistiques souhaitées
  • bibliothèques spécifiques que vous souhaitez utiliser
  • exigences de performance

Pour la programmation côté serveur, vous pouvez souvent choisir parmi une myriade de langages différents, compilés ou interprétés. Généralement, le choix de la langue dépend de la plate-forme sur laquelle vous ou votre équipe allez être le plus efficace. Ou, si vous n'avez pas encore d'équipe, la disponibilité des compétences sur le marché.

En passant, je ne comprends pas vraiment l'idée d'utiliser C / C ++ en fonction des performances (uniquement), car de nombreux langages de script sont extensibles avec C / C ++. Vous bénéficiez d'un langage de développement rapide associé à la possibilité de migrer les parties lentes vers des extensions C / C ++. Bien sûr, si vous faites de la programmation système où chaque opération compte, c'est compréhensible, mais dans la plupart des cas, je ne comprends rien.


2
La familiarité est la raison numéro 1, et je suis surpris que vous soyez le premier à le mentionner.
Paul Butcher

4

C ++ vs Python vs Perl ne peuvent pas être jugés facilement. Cela dépend du projet et des exigences.

C ++ dispose d'un arsenal d'utilitaires d'il y a longtemps, fonctionnant sur de nombreuses plateformes. Mais il est pénible de commencer à parcourir les flux simplement en passant de String à Integer et inversement.

C ++, d’autre part, a beaucoup à faire avec les dépendances aux bibliothèques. Une fois que vous avez compilé quelque chose dans GCC X ou VC ++ Y, vous ne pouvez pas vous fier au code exécuté par la prochaine version de ces outils. Le même enfer est sous Windows, le même enfer est aussi sous Unix.

Perl tire son énergie du monde Unix, mais surtout en tant qu’outil d’expression régulière. C'est ce qu'il est utilisé la plupart du temps. En plus de quelques outils assez sérieux que même Java ne peut pas faire de manière normale (découvrez comment télécharger un fichier sur un serveur Web), Perl est "juste le faire".

Python est un langage simple, flexible et dynamique. Si facile que vous pouvez envoyer un entier à une fonction, le script attend une chaîne, mais vous pouvez avoir un résultat! Inattendu si, mais un résultat. Le programmeur doit donc être très prudent. IDLE offre un peu de débogage, mais lorsque vous avez TELNET dans un système ou SSH dans trois niveaux et que vous voulez trouver votre problème, le débogueur ne sera pas là pour vous accompagner. Mais, il peut faire du bon travail mathématique rapide.

Java est un écosystème de mots à la mode, de technologies extraterrestres et de gros mots. Lorsque vous souhaitez simplement télécharger un fichier sur un serveur Web, vous constatez que vous ne pouvez le faire que si le serveur dispose de JSP . Si vous souhaitez appeler des bibliothèques système ou des fonctions système telles que la surveillance, vous devez creuser beaucoup. Et peut-être pour atteindre JNI et OK ... vous pensez alors ... "Pourquoi, Seigneur?"

En dehors de cela, Java est un excellent outil pour les suites d’affaires et le multithreading, j’ai beaucoup aimé.

Rapide pour faire un programme et montrer à votre CV "Oh, je sais que la technologie aussi" et votre vouloir-être-patron, soyez surpris! Même si, la technologie n’est peut-être pas nécessaire… (OK, les gens, je déteste le Spring Framework ....)


1
hélas, vous devez tenir compte du fait que Python a des dépendances de version - en particulier une fois que vous migrez vers Python 3, de même avec perl .. ou est-ce que quelqu'un a pris la peine de passer à Perl 6? Tout a des dépendances désagréables :(
gbjbaanb

3

Ce qu'il faut garder à l'esprit lors du choix d'une langue, c'est l'avantage que vous en tirerez et le temps qu'il faudra pour l'obtenir.

L'idée principale entre des langages tels que python et perl est de faire plus avec moins de temps, mais avec plus de temps processeur. En fait, vous passerez plus de temps à coder un script python ou perl qu’il ne sera exécuté, mais vous comprenez mon point.

L’avantage du C / C ++ est qu’ils sont rapides, mais à un coût en syntaxe et en typage puissant: vous devez faire beaucoup de choses vous-même pour que l’ordinateur n’ait pas à le choisir au moment de la compilation.

Lorsque vous créez un code, certaines lignes seront exécutées beaucoup plus que d'autres, et ces lignes sont celles qui posent problème. D'autre part, tout le reste du code, celui sur lequel vous avez passé beaucoup de temps, est exécuté beaucoup moins souvent. Vous l'avez peut-être entendu, mais il s'agit de la fameuse règle des 80/20 et vous ne pourrez pas la contourner.

La solution à ce problème consiste à utiliser un langage plus simple (j'entends par plus facile à utiliser pour les développeurs: moins de dactylographie, une interprétation paresseuse, beaucoup de routines préexistantes, etc.) pour faire tout votre code.

Vous le ferez si vite comparé à si vous l'aviez fait avec C ou C ++, cela aurait pris beaucoup plus de mal au cerveau.

Votre programme sera lent, mais avec un profileur, vous isolerez la partie exécutée 80% du temps et vous le ferez en C ou C ++.

En utilisant ce type de programme, vous économisez beaucoup de temps et votre programme est aussi efficace, aussi rapide, moins susceptible de perdre de la mémoire et vous fait gagner du temps.

Les langages de script ont été conçus pour être du côté du développeur, mais l'optimisation est toujours possible. Bien sûr, vous pouvez être un magicien du patron de conception, un vaudou STL ou même un guerrier lisp, et peut-être un moine haskell. Mais les langues nous font parler à des ordinateurs, les langues ne sont pas faites pour être des ordinateurs!



2

Le C ++ que j'utilise s'appelle C avec les classes!


8
Hourra, vous avez utilisé le mot clé 'class'. Maintenant, vous comprenez la conception OO!
dss539

Mon C ++ s'appelle C avec des espaces de noms.
Jsz

6
Mon C ++ s'appelle, euh .. Le C ++ de Manoj.
Manoj R

La classe +1 est la seule raison pour laquelle j'utilise le C ++.
mbq

... ok, aussi des exceptions.
mbq

0

En fait, il n'y a qu'une seule réponse à toutes les questions formées comme celle-ci. La meilleure raison d'utiliser tech X au lieu de tech Y (où X et Y sont à peu près au même niveau [comme presque tous les langages de programmation contemporains le sont]) est parce que vous connaissez déjà X et ne connaissez pas Y.

(mais après l'arrivée de Haskell, il n'y a aucune raison d'utiliser autre chose)


0

Non pas du tout. Si vous n'avez pas besoin de la performance et qu'il y a une bibliothèque, vous pouvez utiliser l'autre langage, alors ne vous embêtez pas avec C / C ++. Je ne le fais que lorsque je cible des systèmes intégrés qui ne peuvent pas (facilement?) Utiliser des langages. Parfois, j'utilise C parce que j'écris un plugin mais vraiment non.

Cependant, je n'utiliserais pas Python, Perl, etc. pour éviter d'utiliser C. Ma préférence est en fait C #, car j'aime une bonne bibliothèque (qui est une force de .NET) et j'aime les langages à typage statique. Boo est une bonne alternative. Mais en réalité, Haskell , OCaml , D , ML , etc.


7
Vous avez manqué le point.
Matt Joiner

@ Matt Joiner: Je suis sûr que non. Qu'est-ce que j'ai raté?

La question est de ne pas utiliser C ++.
Matt Joiner

@ Matt Joiner: hmm, sur un autre regard, je peux voir que cela est demandé. Mais il semble que j'ai répondu à ça aussi (j'ai dit ne vous embêtez pas et les alternatives que j'utilise)

J'ai presque envie de changer cela à cause de C # ...
Vreality
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.