web-dev-qa-db-fra.com

Pourquoi devrais-je apprendre le C ++ 11, après avoir connu le C et le C ++?

Je suis programmeur en C et C++, bien que je ne m'en tiens pas à l'un ou l'autre des langages et que j'écris un mélange des deux. Parfois, avoir du code dans les classes, peut-être avec une surcharge d'opérateur, ou des modèles et le oh so great STL est évidemment une meilleure façon. Parfois, l'utilisation d'un simple pointeur de fonction C est beaucoup plus lisible et claire. Je trouve donc la beauté et l'aspect pratique dans les deux langues. Je ne veux pas entrer dans la discussion de "Si vous les mélangez et compilez avec un compilateur C++, ce n'est plus un mélange, c'est tout C++" Je pense que nous comprenons tous ce que je veux dire en les mélangeant. De plus, je ne veux pas parler de C vs C++, cette question concerne C++ 11.

C++ 11 introduit ce que je pense être des changements importants dans le fonctionnement de C++, mais il a introduit de nombreux cas spéciaux, exceptions et irrégularités qui changent la façon dont différentes fonctionnalités se comportent dans différentes circonstances, imposant des restrictions sur l'héritage multiple, des identificateurs qui agissent comme des mots clés, des extensions des littéraux de chaîne, capture de variable de fonction lambda, etc.

Je sais qu'à un moment donné dans le futur, quand vous dites C++, tout le monde supposerait C++ 11. Tout comme lorsque vous dites C de nos jours, vous voulez probablement dire C99. Cela me fait envisager d'apprendre C++ 11. Après tout, si je veux continuer à écrire du code en C++, il se peut qu'à un moment donné, je doive commencer à utiliser ces fonctionnalités simplement parce que mes collègues l'ont fait.

Prenez C par exemple. Après tant d'années, il y a encore beaucoup de gens qui apprennent et écrivent du code en C. Pourquoi? Parce que la langue est bonne. Ce qui signifie bien, c'est qu'il suit de nombreuses règles pour créer un bon langage de programmation. Donc, en plus d'être puissant (ce qui est facile ou difficile, presque tous les langages de programmation le sont), C est régulier et a quelques exceptions, le cas échéant. C++ 11 cependant, je ne pense pas. Je ne suis pas sûr que les changements introduits dans C++ 11 améliorent le langage.

La question est donc: Pourquoi devrais-je apprendre le C++ 11?

28
anon

Vous devriez l'apprendre si vous pensez avoir besoin de le savoir à l'avenir pour obtenir un emploi. Si vous êtes convaincu que vous resterez commercialisable sur le marché du travail en tant que C/C++ [et tout ce que vous pourriez savoir], alors ne l'apprenez pas. Si votre patron vous dit d'utiliser C++ 11, dites "non, je ne fais pas ça". S'il vous congédie, allez travailler ailleurs. Apprenez le C++ 11 lorsque vous prévoyez que bientôt vous ne pourrez pas trouver un emploi satisfaisant avec les compétences que vous connaissez actuellement.

Je voulais clarifier ma justification: je ne suis pas anti-C++ 11. Je dis simplement que vous pouvez généraliser la question du PO à "Pourquoi devrais-je apprendre X". Je n'ai jamais appris le ML, le schéma ou le haskell parce que j'ai un travail avec C et C++. Je suis sûr que ces langues sont utiles à quelqu'un, mais elles ne me sont pas utiles pour le moment. Si quelqu'un m'offrait beaucoup d'argent pour programmer en ML, je pourrais essayer de l'apprendre.

24
Timmah

C'est simple. C++ 11 rend le code beaucoup plus facile, plus propre à écrire et plus rapide.

nullptr est une VASTE amélioration par rapport à l'ancienne 0. Il est sûr pour le type et ne convertit pas quand il ne devrait pas - contrairement à 0. C'est une bonne chose que nullptr ne convertira pas en int. Cela n'a aucun sens que cela se produise du tout. Savez-vous ce que le Comité C++ a trouvé lorsqu'il a essayé de considérer #define NULL nullptr? Choses comme char c = NULL;. C'est terrible, non? La seule raison pour laquelle il y a une exception ici est parce que bool est considéré comme un type intégral, ce qui est tout à fait faux - mais qui était là en C++ avant et en C. Le fait que nullptr ne le fasse pas convertir est bon, c'est excellent et vous devriez l'adorer.

Ou que diriez-vous des références de valeur et des modèles variadic? Code plus rapide et plus générique. C'est une victoire totale ici.

Qu'en est-il des améliorations de la bibliothèque? Des trucs comme function, unique_ptr et shared_ptr sont tellement meilleurs qu'avant, il est impossible d'affirmer que la méthode C++ 03 était meilleure.

#define adding_func(x, y) ((x)+(y))

Pas même à distance équivalent. Les macros sont mauvaises pour six milliards de raisons. Je ne vais pas tous les citer ici, mais il est bien connu que les macros doivent être évitées à peu près à toutes les fins pour lesquelles elles peuvent éventuellement être évitées. Qu'allez-vous faire quand ce sera

#define add_twice(x) (x + x)

Oh, attendez, j'espère que vous n'avez pas augmenté ou quelque chose sur x. À laquelle la version de la fonction de modèle est totalement immunisée. J'espère également que vous n'appréciez pas espaces de noms, par exemple.

Ensuite, vous vous ouvrez à un monde de comportements indéfinis pour utiliser des variables externes dont les étendues sont déjà terminées.

Dans une API fonctionnelle, par exemple Algorithmes STL, la référence est correcte. S'il s'agit d'un rappel stocké, vous devez capturer par valeur. Quelle que soit la documentation que vous avez sur la fonction, elle doit indiquer clairement celle qui est nécessaire. Le fait que le code soit écrit dans un lambda est sans importance pour le problème de référence aux variables locales - si vous passez un objet de fonction régulière, alors vous allez avoir exactement le même problème. Et ce n'est pas un problème. Du tout. Parce qu'il est intrinsèquement évident lorsque vous pouvez et ne pouvez pas faire référence à des variables locales.

Prenez C par exemple. Après tant d'années, il y a encore beaucoup de gens qui apprennent et écrivent du code en C. Pourquoi?

Il y a beaucoup de gens qui ne se brossent pas les dents le matin. Il y a beaucoup de meurtriers, de violeurs et de prostituées. Et les politiciens. Les gens qui se suicident. Diriez-vous que cela rend donc ces activités bonnes ou utiles? Bien sûr que non. C'est une erreur logique que juste parce que quelqu'un l'a fait, elle doit donc être bonne ou utile.

C est toujours en cours d'écriture pour trois raisons: parce que C++ est une chienne à implémenter, par exemple en mode embarqué ou noyau; parce que les bases de code héritées sont écrites en C et coûteraient trop cher à mettre à niveau, même si cela est douteux étant donné l'excellent interopérabilité de C++; et parce que les gens qui l'écrivent ne savent pas programmer. C'est ça. Il n'y a pas d'autre raison d'écrire C.

Si vous prenez C ou l'ancien C++, vous ne trouverez pas beaucoup d'exceptions.

Que diriez-vous des tableaux pathétiques de style C, pour un exemple simple? Le nombre de personnes qui ne peuvent pas obtenir des tableaux et des pointeurs directement dans leur tête est obscène. Sans parler du fait que la bibliothèque C Standard est incroyablement dangereuse.

Vos principaux arguments sont pleins d'erreurs logiques et de malentendus.

85
DeadMG

C++ 11 n'est pas un nouveau langage; ce n'est qu'une extension/modification de C++ que vous connaissez déjà. C++ 11 comme tout autre langage de programmation se compose de fonctionnalités. Beaucoup d'entre eux étaient là avant, certains sont nouveaux. Mais votre question est vraiment, dois-je apprendre toutes les fonctionnalités du langage (dans ce cas C++ 11), ou seulement me familiariser avec 90% de celui-ci?

IMO même si vous n'utilisez pas toute la langue, vous devriez au moins lire ce que les nouvelles fonctionnalités font pour vous. Beaucoup d'entre eux ont été introduits pour faciliter l'écriture du code de bibliothèque/framework (en particulier les modèles) (par exemple, avant que le transfert parfait en C++ 11 ne soit impossible), mais si vous n'avez jamais eu besoin de cette fonctionnalité auparavant, vous avez probablement des chances de gagner notez pas que ces fonctionnalités ont été ajoutées en C++ 11.

D'un autre côté, si vous avez déjà essayé d'écrire du code de bibliothèque/noyau qui imite certaines des fonctionnalités STL/Boost et que vous vous êtes trouvé limité par le langage parce que vous avez atteint 95% d'avoir une solution très cool et élégante mais vous avez été arrêté parce que vous avez découvert que le langage ne supporte tout simplement pas ce que vous voulez, vous réaliserez la puissance vraiment impressionnante de C++ 11. Depuis que notre équipe est passée à VS2010 (et nous avons découvert Boost dans le processus), j'ai été en mesure de lancer un code génial fou, qui serait tout simplement impossible avant des choses comme les références de valeur r et la transmission des paramètres de modèle.

Des choses comme celles de lambda peuvent aussi sembler étrangères, mais elles n'introduisent pas de nouvelle construction. Au lieu de cela, ils rendent ce que nous avions avant tellement plus facile à écrire. Auparavant, chaque fonction lambda devait être une classe distincte. Maintenant, c'est juste {... code ...}. Aimer.

La clé est de ne pas regarder ces fonctionnalités et de penser à quel point la liste est intimidante. Au lieu de cela, utilisez C++ comme vous le faites normalement et lorsque vous rencontrerez un scénario où ces nouvelles fonctionnalités C++ 11 seront utiles (plus de 90% des personnes n'y arriveront jamais), vous serez très heureux que l'extension à la langue a été fait. Pour l'instant, je vous suggère d'en apprendre suffisamment sur la langue pour savoir ce qu'il y a, pas nécessairement comment l'utiliser.

29
DXM

Est-il si difficile d'écrire une fonction, que vous devez écrire le contenu de la fonction en ligne avec le code, en plus de ne lui donner aucun nom?

Lorsque vous faites cela, faites défiler vers le haut ou ouvrez un nouveau fichier source et ajoutez-y la définition de la fonction. Ensuite, vous devez revenir en arrière et continuer sur ce sur quoi vous travailliez, ce qui vous distrait dans une certaine mesure.

En dehors de cela, lorsque d'autres personnes vous lisent, un code lambda peut être plus auto-documenté dans certains cas, au lieu de dire "Oh, que fait cette fonction?" et en sautant sur sa déclaration, vous pouvez simplement jeter un œil à ce qu'il fait à sa place.

Il y a une belle discussion par Herb Sutter sur les lambdas, peut-être qu'il peut mieux vous convaincre:

http://channel9.msdn.com/events/PDC/PDC10/FT1

Eh bien, pourquoi n'y écrivez-vous pas simplement le code au lieu d'en faire une fonction lambda?

Parce que vous ne pouvez pas le faire lorsque vous utilisez des algorithmes STL ou toute fonction que vous utilisez et qui vous oblige à passer une fonction.

#define add_func (x, y) ((x) + (y))

Il n'y a aucun moyen de justifier cette utilisation au lieu de lambdas, vous ne pouvez pas remplir votre code avec des macros partout. Les macros et les fonctions ont des objectifs différents, et l'une, en général, ne remplace pas l'autre.

template<class Lhs, class Rhs>
auto adding_func(const Lhs &lhs, const Rhs &rhs)
                -> decltype(lhs+rhs) {return lhs + rhs;}

Je suis d'accord, c'est moche. Cependant je me souviens avoir dit "pourquoi diable devrais-je comprendre le type de cette expression même si le compilateur peut en déduire cela?" dans de nombreux cas. Cela pourrait aider beaucoup pendant ces moments.

Pour résumer:

Même si les nouvelles fonctionnalités de C++ 11 semblent laides dans leur syntaxe, je pense que l'on peut s'y habituer en peu de temps. Chaque nouvelle construction de langage est difficile à apprendre au début; imaginez la première fois que vous avez appris à écrire une classe entière: Mettre la déclaration dans le fichier d'en-tête, sans oublier le point-virgule supplémentaire à la fin, mettre les définitions dans le fichier source, y compris le fichier d'en-tête tout en s'assurant qu'il a une garde pour empêcher inclusions multiples, sans oublier l'opérateur de résolution de portée dans les déclarations de fonctions membres et ainsi de suite ...

Mais je suis à peu près sûr qu'après avoir écrit quelques classes, vous vous y habituez, et vous ne pensez pas à la complexité de ce processus: parce que vous savez qu'une classe rend votre travail de programmeur beaucoup plus facile, et le utilité que vous gagnez de cette nouvelle construction est beaucoup plus grande que la perte d'utilité pendant le temps que vous essayiez d'apprendre la langue. Je pense que cela peut être la raison pour laquelle on devrait essayer d'apprendre, ou utiliser C++ 11 d'une manière similaire.

18
loudandclear

En fait, le PO a quelques points, comme la plupart des réponses. Mais ils sont "distants" dans leur vision. Le C++ (y compris le sous-ensemble C) a une longue histoire où un certain nombre de fonctionnalités ont été ajoutées au fil du temps, certaines d'entre elles étant utilisées plus ou moins fréquemment et - à travers leur utilisation et leurs erreurs - perfectionnées en d'autres et d'autres.

Parfois, il arrive qu'après l'introduction d'une nouvelle fonctionnalité, une ancienne soit plus nécessaire ou se sente en contradiction avec elle. Un langage "propre" doit être auto-cohérent tel qu'il est, et les fonctionnalités qui ne sont plus nécessaires doivent être supprimées.

Mais l'ajout ne détruit rien. La suppression (ou la modification) casse le code existant qu'il est toujours en production, donc quelle que soit la fonctionnalité que vous ajoutez, vous devez prendre soin de ne pas casser le code existant (en particulier, ne le cassez pas en silence, en faisant faire des choses différentes comme prévu).

Devez-vous apprendre tout cela? Oui, car toutes les fonctionnalités sont utilisées, en bien ou en mal, tôt ou tard. Que ce soit une bonne chose pour la "qualité" de la langue (en admettant qu'il existe une mesure objective) est une autre histoire: combien de temps la compatibilité ascendante doit-elle être conservée? difficile de trouver une réponse, quand quelqu'un dit 3 ans et certains disent 50.

L'alternative pour garder le C++ plus "régulier" est ... de le casser plus souvent, avec un redémarrage scratch. Mais ce ne sera plus du C++.

Il y a des tentatives pour le faire aussi (pensez à D, par exemple: beaucoup plus orthogonal que le C++ (même 11)), mais quelle est leur popularité? L'une des raisons de leur difficulté à avoir un élan est l'incompatibilité avec de nombreux codes existants qui doivent encore s'exécuter.

C++ 11, pour moi, est clairement un compromis entre les nouveaux besoins et la compatibilité descendante. Cela a entraîné un certain "désordre" de ses spécifications et de sa mise en œuvre. Jusqu'à ce que le coût de ce "désordre" soit inférieur au coût de l'incompatibilité ... vous devez partir avec ce compromis.

Si vous ne pouvez plus le tolérer, ... mieux vaut envisager une autre langue plus jeune. C++ ne peut tout simplement pas être simplifié dans ce sens. Pas à cet âge.

8

Même si vous décidez d'ignorer les nouvelles fonctionnalités C++ 11, vous en bénéficierez toujours car la bibliothèque standard C++ les utilisera. Par exemple, en C++ 98 ayant une variable de type vector<string> était potentiellement un gâchis de performances en raison du nombre de copies à réaliser lors de la croissance du vecteur. Avec le constructeur de déplacement C++ 11, ce n'est pas un problème. En fait, je souhaite que C++ 11 nous apporte plus de nouvelles fonctionnalités, pas moins - en particulier dans la bibliothèque standard.

7

Après tant d'années, il y a encore beaucoup de gens qui apprennent et écrivent du code en C. Pourquoi? Parce que la langue est bonne.

Premièrement, la plupart des étudiants de nos jours apprennent Java ou .NET, pas C. Deuxièmement, les gens utilisent toujours C non seulement à cause de ses avantages en tant que langage, mais principalement parce qu'il y a énormément des logiciels existants écrits en C qui doivent être maintenus et étendus, et parce que dans de nombreux cas (par exemple, les plates-formes embarquées), un compilateur C est tout ce qu'il y a.

Il est très rare qu'un programmeur de l'industrie commence à travailler sur un tout nouveau projet qui n'est pas lié à une base de code existante et continue à travailler seul. Ainsi, la raison d'apprendre C++ 11 est que vous devrez probablement traiter avec du code écrit par d'autres personnes, qui utilise les nouvelles fonctionnalités. En outre, les fonctionnalités qui ont été ajoutées ont été ajoutées pour une raison. Une fois que vous les apprenez et les utilisez, vous pourriez les apprécier.

6
Dima
  • L'assembly a été créé parce que les gens n'aimaient pas écrire du code machine
  • C a été créé parce que les gens n'aimaient pas écrire Assembly
  • C++ a été créé parce que les gens n'aimaient pas écrire C
  • C++ 11 a été créé parce que les gens n'aimaient pas écrire C++

Vous allez arriver à un point de votre carrière C++ où vous vous dites: "Je souhaite que les foncteurs soient plus simples," ou "Pourquoi NULL est-il un int?" puis vous comprendrez C++ 11.

5
Pubby

Vous devez apprendre le C++ 11 car les fonctionnalités ajoutées vous permettent d'écrire un meilleur code. Certaines personnes ont mentionné la sécurité des pointeurs NULL et des lambdas, qui sont très agréables. Mais je veux attirer l'attention sur ce que je pense être le changement le plus spectaculaire en C++ 11, en particulier dans un grand environnement de production: déplacer la sémantique.

C++ 11 prend en charge des notions distinctes de "déplacement" et de "copie". En C++ normal, nous avons juste l'opérateur = qui fait essentiellement les deux. Mais vraiment, nous exprimons deux idées distinctes avec un seul opérateur, ce qui est dangereux.

L'exemple le plus évident où cela est utile est le nouveau unique_ptr. Il possède toutes les meilleures fonctionnalités des anciens auto_ptr et scoped_ptr. Supposons que nous voulons avoir un pointeur qui est garanti d'être le seul pointeur pointant vers un objet. Comment traitons-nous avec a = b? Eh bien, avant, nous étions bloqués, vous pouviez soit le refuser complètement (comme scoped_ptr), soit faire ce que auto_ptr fait quand a = b vole la propriété à b. Ce comportement de auto_ptr est très déroutant car a = b change en fait b. unique_ptr gère cela: a = b n'est pas autorisé, mais vous avez a = std :: move (b) pour voler la propriété. Comment est-ce utile? Où, il existe une version séparée (surchargée) de swap qui utilise la sémantique de déplacement plutôt que la sémantique de copie. Cela signifie que ce unique_ptr peut être échangé, pas de problème. Cela signifie que unique_ptr, contrairement à auto_ptr, peut être utilisé en toute sécurité dans un conteneur, puis dire tri. unique_ptr est fondamentalement la solution de gestion de la mémoire sécurisée lorsque vous n'avez pas besoin de plusieurs pointeurs sur le même objet.

Un autre excellent exemple: supposons que vous ayez un objet qui n'est pas copiable. Ceci est utile dans un certain nombre de situations. Vous ne pouvez jamais renvoyer cet objet à partir d'une fonction, car lorsque la fonction se termine, elle copie tout ce que vous retournez. L'ironie est que généralement le compilateur optimise réellement cela (c'est-à-dire que rien n'est réellement copié à la fin, la valeur de retour est créée à l'adresse de l'affectation éventuelle). Mais cela n'a rien à voir avec la raison pour laquelle nous l'avons rendu non copiable; le retour d'une fonction ne fait que déplacer l'objet de l'intérieur de la portée de la fonction vers l'extérieur. Vous pouvez maintenant écrire des objets qui ne sont pas copiables mais SONT mobiles, et ces objets peuvent être renvoyés par les fonctions.

La sémantique de déplacement facilite l'écriture de code qui ne fuit pas et qui est sûr pour les threads.

4
Nir Friedman

L'apprentissage est toujours bénéfique. La connaissance, c'est le pouvoir.

Voilà la réponse, essentiellement. Tout le reste n'est que des détails sur la façon dont vous pouvez en bénéficier et quels pouvoirs vous avez en le sachant, et ils sont si nombreux que toute énumération serait incomplète.

Un exemple est votre propre question. Vous ne pourriez même pas le demander sans en apprendre au moins un peu.

Et comme je l'ai commenté - la vraie préoccupation n'est pas pourquoi apprendre, mais pourquoi tiliser. Et c'est une question entièrement différente.

4
littleadv