J'ai récemment appris le D et je commence à me familiariser avec la langue. Je sais ce que ça offre, je ne sais pas encore tout utiliser, et je ne connais pas grand chose au sujet des idiomes D, etc., mais j'apprends.
J'aime D. C'est un bon langage, étant, d'une certaine manière, une énorme mise à jour de C, et bien fait. Aucune de ces caractéristiques ne semble être "intégrée", mais en réalité assez bien pensée et bien conçue.
Vous entendrez souvent dire que D est ce que C ++ aurait dû être (je laisse la question de savoir si chacun doit décider lui-même afin d'éviter des guerres de flammes inutiles). J'ai également entendu plusieurs programmeurs C ++ affirmer qu'ils appréciaient beaucoup plus le C ++.
Moi-même, alors que je connais le C, je ne peux pas dire que je connais le C ++. J'aimerais entendre quelqu'un qui connaît à la fois C ++ et D s'il pense qu'il y a quelque chose que C ++ fait mieux que D en tant que langage (c'est-à-dire pas l'habituel "il a plus de bibliothèques tierces" ou "il y a plus de ressources" ou " plus de travaux nécessitant C ++ que D existe ").
D a été conçu par des programmeurs C ++ très expérimentés ( Walter Bright et Andrei Alexandrescu , avec l’aide de la communauté D) pour résoudre de nombreux problèmes du C ++, mais y avait-il quelque chose qui ne s’est pas amélioré après tout? Quelque chose lui a manqué? Quelque chose que tu penses n'était pas une meilleure solution?
Réponses:
La plupart des choses que C ++ "fait" mieux que D sont méta choses: C ++ a de meilleurs compilateurs, de meilleurs outils, des bibliothèques plus matures, plus de liaisons, plus d'experts, plus de tutoriels, etc. Fondamentalement, il a plus et mieux attendrait d'un langage plus mature. C'est indiscutable.
En ce qui concerne le langage lui-même, il y a quelques choses que C ++ fait mieux que D à mon avis. Il y a probablement plus, mais en voici quelques-unes que je peux en citer:
C ++ a un système de types mieux pensé
Il existe actuellement quelques problèmes avec le système de types en D, qui semblent être des oublis dans la conception. Par exemple, il est actuellement impossible de copier une structure const dans une structure non-const si celle-ci contient des références à des objets de classe ou des pointeurs en raison de la transitivité de const et de la manière dont les constructeurs postblit travaillent sur les types valeur. Andrei dit qu'il sait comment résoudre ce problème, mais n'a donné aucun détail. Le problème est certainement réparable (introduire des constructeurs de copie de style C ++ serait un correctif), mais c’est un problème majeur de langage à l’heure actuelle.
Un autre problème qui m'a posé problème est le manque de const logique (c'est-à-dire pas
mutable
comme en C ++). C'est très bien pour écrire du code thread-safe, mais il est difficile (impossible?) De faire une initialisation lente dans les objets const (pensez à une fonction const 'get' qui construit et met en cache la valeur renvoyée lors du premier appel).Enfin, compte tenu de ces problèmes existants, je suis inquiet sur la façon dont le reste du système de type (
pure
,shared
, etc.) va interagir avec tout le reste dans la langue une fois qu'ils sont mis à contribution . La bibliothèque standard (Phobos) utilise actuellement très peu le système de types avancé de D, je pense donc qu'il est raisonnable de se demander si elle résistera au stress. Je suis sceptique mais optimiste.Notez que C ++ a des verrous de système de types (par exemple, const non transitive, nécessitant
iterator
aussi bien queconst_iterator
) qui le rendent assez laid, mais si le système de types de C ++ est un peu faux à certains endroits, cela ne vous empêche pas de faire un travail comme D fait parfois.Edit: Pour clarifier, je pense que C ++ a un système de types mieux pensé - pas nécessairement meilleur - si cela a du sens. En DI, nous estimons qu’il est risqué d’utiliser tous les aspects de son système de types qui ne sont pas présents en C ++.
D est parfois un peu trop pratique
Une des critiques que vous entendez souvent à propos du C ++ est qu’il vous cache certains problèmes de bas niveau, par exemple, de simples tâches comme
a = b;
faire des opérateurs comme des opérateurs de conversion, des opérateurs d’attribution de surcharge, etc. difficile à voir à partir du code. Certaines personnes aiment ça, d'autres non. De toute façon, en D , il est pire (mieux?) À cause de choses commeopDispatch
,@property
,opApply
,lazy
qui ont le potentiel de changer le code air innocent dans les choses que vous ne penserez pas.Je ne pense pas que ce soit un gros problème personnellement, mais certains pourraient trouver cela déconcertant.
D nécessite le ramassage des ordures.
Cela peut être considéré comme controversé car il est possible de lancer D sans le GC. Cependant, ce n'est pas parce que c'est possible que c'est pratique. Sans GC, vous perdez beaucoup de fonctionnalités de D, et utiliser la bibliothèque standard équivaudrait à marcher dans un champ de mines (qui sait quelles fonctions allouent de la mémoire?). Personnellement, j'estime qu'il est totalement irréaliste d'utiliser D sans GC, et si vous n'êtes pas fan des GC (comme moi), cela peut être assez rébarbatif.
Les définitions de tableaux naïfs en D allouent la mémoire
C'est une bête noire des animaux:
Apparemment, pour éviter l'attribution dans D, vous devez faire:
Ces petites allocations "derrière le dos" sont de bons exemples de mes deux précédents points.
Edit: Notez qu’il s’agit d’un problème connu en cours de traitement.Edit: Ceci est maintenant corrigé. Aucune attribution n'a lieu.
Conclusion
Je me suis concentré sur les aspects négatifs de D par rapport à C ++ parce que c'est la question qui a été posée, mais s'il vous plaît, ne considérez pas ce message comme une déclaration selon laquelle C ++ est meilleur que D. Je pourrais facilement créer un plus grand nombre de lieux où D est meilleur que C ++. C'est à vous de décider lequel utiliser.
la source
Quand j'ai rejoint D development, j'étais dans la position particulière d'être l'une des personnes les plus informées sur le C ++. Maintenant, je suis dans une position encore plus singulière pour faire partie de ceux qui savent le plus à propos de D. Je ne dis pas cela pour obtenir un crédit ou des droits de vantardise, mais pour vous faire remarquer que je suis curieusement curieux. position privilégiée pour répondre à cette question. La même chose s'applique à Walter.
De manière générale, demander ce que C ++ (et j'entends par là C ++ 2011) fait mieux que D est aussi contradictoire que la question: "Si vous payez un professionnel pour nettoyer votre maison, quels sont les lieux qu’ils laisseront plus sale qu'avant? " Quelle que soit sa valeur, C ++ pouvait faire ce que D ne pouvait pas faire, cela a toujours été comme une blessure au pouce pour moi et Walter, donc presque par définition, rien que C ++ ne puisse faire qui ne soit pas à la portée de D.
Une chose qui est rarement comprise dans la conception du langage (car peu de gens ont la chance d’en faire) est qu’il ya beaucoup moins d’erreurs non forcées qu’il n’apparaît. Beaucoup d’entre nous, utilisateurs de langues, regardons une construction ou une autre et disent: "Ew! C’est tellement faux! A quoi pensaient-ils?" Le fait est que la plupart des instances maladroites dans une langue sont le résultat de quelques décisions fondamentales qui sont toutes judicieuses et souhaitables, mais qui se font fondamentalement concurrence ou se contredisent (par exemple, modularité et efficacité, intégrité et contrôle, etc.).
Cela étant dit, je vais énumérer quelques éléments auxquels je peux penser et expliquer pour chacun le lien entre le choix de D et son désir de respecter une autre charte de niveau supérieur.
D suppose que tous les objets sont déplaçables par copie binaire. Cela laisse une minorité de conceptions au C ++, en particulier celles qui utilisent des pointeurs internes, c'est-à-dire une classe contenant des pointeurs à l'intérieur de lui-même. (Toute conception de ce type peut être traduite en D avec un coût d'efficacité nul ou négligeable, mais un effort de traduction serait nécessaire.) Nous avons pris la décision de simplifier considérablement le langage, de rendre la copie d'objet plus efficace avec une intervention minimale ou minimale de l'utilisateur, et d'éviter tout le maras de la construction de la copie et les références rvalue sont complètement présents.
D interdit les types de genre ambigus (qui ne peuvent pas décider s'il s'agit de types valeur ou référence). De telles conceptions sont unanimement rejetées en C ++ et presque toujours fausses, mais certaines sont techniquement correctes. Nous avons fait ce choix car il interdit la plupart du temps un code incorrect et une infime fraction de code correct pouvant être redessiné. Nous croyons que c'est un bon compromis.
D interdit les hiérarchies à plusieurs racines. Une précédente affiche ici était très enthousiasmée par ce sujet particulier, mais il s’agit d’un terrain bien parcouru et il n’ya aucun avantage palpable des hiérarchies sans racines sur des hiérarchies qui ont toutes une racine commune.
En D, vous ne pouvez pas lancer, par exemple, un int. Vous devez lancer un objet héritant de Throwable. Nul ne conteste que la situation est meilleure en D, mais bon, c’est une chose que C ++ peut faire que D ne le peut pas.
En C ++, l'unité d'encapsulation est une classe. En D c'est un module (c'est-à-dire un fichier). Walter a pris cette décision pour deux raisons: mapper naturellement l’encapsulation sur la sémantique de la protection du système de fichiers et éviter le besoin de "ami". Ce choix s’intègre très bien dans la conception globale de la modularité de D. Il serait possible de changer les choses pour ressembler davantage à C ++, mais cela forcerait les choses; Les choix d'étendue d'encapsulation de C ++ ne sont utiles que pour la conception physique de C ++.
Il pourrait y avoir une ou deux petites choses, mais globalement, ça devrait être ça.
la source
Object*
aussi largement utilisé qu'unint*
??) Et D semble ignorer complètement la pénalité de performance, ou le prétendant n'existe pas. C'est évidemment faux - le manque de mémoire cache est assez visible dans de nombreux cas, donc C ++ aura toujours cet avantage enJe pense que vous allez avoir beaucoup de mal à trouver beaucoup dans D qui est objectivementpire que C ++. La plupart des problèmes avec D où vous pourriez objectivement dire que c'est pire sont soit des problèmes de qualité d'implémentation (qui sont généralement dus à la jeunesse du langage et de l'implémentation qui ont été corrigés à une vitesse vertigineuse), ou ce sont des problèmes avec un manque de bibliothèques tierces (qui viendra avec le temps). Le langage lui-même est généralement meilleur que le C ++, et les cas où C ++, en tant que langage, est meilleur sont généralement ceux où il y a un compromis où C ++ est allé dans un sens et D est allé dans un autre, ou lorsque quelqu'un a des raisons subjectives pour lesquelles il a pense que l'un est meilleur qu'un autre. Mais le nombre de raisons objectives pour lesquelles C ++, en tant que langage, est meilleur est susceptible d’être rare.
En fait, je dois vraiment me casser la tête pour trouver les raisons pour lesquelles le langage C ++ est meilleur que le langage D. Ce qui me vient généralement à l’esprit est une question de compromis.
Comme le const de D est transitif et que le langage est immuable , il a des garanties bien plus solides que le C ++
const
, ce qui signifie que D n’a pas et ne peut pas avoirmutable
. Il ne peut pas avoir de logique . Vous obtenez donc un gain énorme avec le système const de D, mais dans certaines situations, vous ne pouvez pas utiliserconst
comme vous le feriez en C ++.D n'a qu'un seul opérateur de conversion, alors que C ++ en a 4 (5 si vous comptez l'opérateur de conversion C). Cela facilite le traitement des castes en D dans le cas général, mais est problématique lorsque vous voulez réellement les complications / avantages supplémentaires que
const_cast
fournissent ses frères. Mais D est en fait assez puissant pour que vous puissiez utiliser des modèles pour implémenter les transts C ++. Si vous les voulez vraiment, vous pouvez les avoir (et ils peuvent même se retrouver dans la bibliothèque standard de D à un moment donné).D a beaucoup moins de conversions implicites que C ++ et est beaucoup plus susceptible de déclarer que deux fonctions sont en conflit (ce qui vous oblige à préciser davantage la fonction que vous voulez dire - avec des conversions ou en donnant le chemin complet du module ) Parfois, cela peut être ennuyeux, mais cela évite toutes sortes de problèmes de détournement de fonction . Vous savez que vous appelez vraiment la fonction que vous voulez dire.
Le système de modules de D est bien plus propre que celui de C ++ (sans oublier, beaucoup plus rapide à la compilation), mais il lui manque tout type d’espace de nommage au-delà des modules eux-mêmes. Donc, si vous voulez un espace de noms dans un module, vous devez utiliser la route Java et utiliser des fonctions statiques sur une classe ou une structure. Cela fonctionne, mais si vous voulez vraiment un espacement de noms, ce n'est évidemment pas aussi net qu'un véritable espacement de noms. Cependant, dans la plupart des situations, les modules vous fournissent une grande quantité de noms (et assez sophistiqués pour les conflits, par exemple).
Comme Java et C #, D possède un héritage unique plutôt qu’un héritage multiple, mais contrairement à Java et C #, il vous offre des moyens fantastiques d’obtenir le même effet sans tous les problèmes que l’héritage multiple de C ++ a (l’héritage multiple de C ++ peut devenir très compliqué.) a l'heure). Non seulement D ont des interfaces , mais il a mixins chaîne , mixins modèle , et alias ce . Ainsi, le résultat final est sans doute plus puissant et ne présente pas tous les problèmes inhérents à l'héritage multiple de C ++.
Semblable à C #, D sépare les structures et les classes . Les classes sont des types de référence qui ont un héritage et qui en sont dérivés
Object
, alors que les structures sont des types de valeur sans héritage. Cette séparation peut être à la fois bonne et mauvaise. Il supprime le problème de découpage classique en C ++ et permet de séparer les types qui sont réellement des types de valeur de ceux qui sont supposés être polymorphes, mais au début, au moins, la distinction pourrait être gênante pour un programmeur C ++. En fin de compte, il y a un certain nombre d'avantages, mais cela vous oblige à traiter vos types un peu différemment.Les fonctions membres des classes sont polymorphes par défaut. Vous ne pouvez pas les déclarer non virtuels . Il appartient au compilateur de décider s’ils peuvent le faire (ce qui n’est vraiment le cas que s’ils sont finaux et qu’ils ne remplacent pas une fonction d’une classe de base). Donc, cela pourrait être un problème de performance dans certains cas. Cependant, si vous n'avez vraiment pas besoin du polymorphisme, tout ce que vous avez à faire est d'utiliser des structures , et ce n'est pas un problème.
D possède un ramasse - miettes intégré . Beaucoup de C ++ considèrent que c'est un sérieux inconvénient, et à la vérité, sa mise en œuvre pourrait nécessiter un travail sérieux. Les choses s'améliorent, mais ce n'est certainement pas encore à égalité avec le ramasse-miettes de Java. Cependant, ceci est atténué par deux facteurs. Premièrement, si vous utilisez principalement des structures et d'autres types de données sur la pile, le problème n'est pas grave. Si votre programme n'alloue pas et ne désalloue pas constamment des choses sur le tas, tout ira bien. Et deuxièmement, vous pouvez ignorer le ramasse - miettes si vous le souhaitez et utiliser simplement les lettres C
malloc
etfree
. Certaines fonctionnalités linguistiques (telles que le découpage en matrice) que vous devrez éviter ou avec prudence, et une partie de la bibliothèque standard ne sera pas réellement utilisable sans au moins quelques utilisations du GC (en particulier du traitement de chaîne), mais vous pouvez écrire en D sans utiliser le garbage collector si tu veux vraiment. La chose intelligente à faire est probablement de l’utiliser généralement et de l’éviter ensuite lorsque le profilage montre que cela pose des problèmes pour le code critique en termes de performances, mais vous pouvez l’éviter complètement si vous le souhaitez. Et la qualité de la mise en œuvre du GC s'améliorera avec le temps, éliminant ainsi bon nombre des problèmes que l'utilisation d'un GC peut causer. Donc, au final, le GC ne sera pas un aussi gros problème et, contrairement à Java, vous pouvez l'éviter si vous le souhaitez.Il y en a probablement aussi d'autres, mais c'est ce que je peux proposer pour le moment. Et si vous remarquerez, ce sont tous des compromis. D a choisi de faire certaines choses différemment du C ++, qui présentent des avantages certains par rapport à la façon dont C ++ les fait, mais qui présentent également certains inconvénients. Ce qui est mieux dépend de ce que vous faites, et dans de nombreux cas, cela ne semblera probablement qu'empirer au début et vous ne rencontrerez plus de problème une fois que vous y serez habitué. En fait, les problèmes de D vont généralement être nouveaux et causés par de nouvelles choses que d’autres langages n’ont pas encore utilisées ou qui ont été faites de la même manière que D. Globalement, D a très bien appris des erreurs de C ++.
Et D, en tant que langage, s’améliore sur le C ++ de tant de façons que je pense que c’est généralement le cas que D est objectivement meilleur.
D a une compilation conditionnelle . C'est l'une des fonctionnalités que je manque souvent lorsque je programme en C ++. Si C ++ l’ajoute, alors C ++ s’améliorera à pas de géant en ce qui concerne des éléments tels que les modèles.
D a une réflexion au moment de la compilation .
Les variables sont locales aux threads par défaut, mais peuvent l'être
shared
si vous le souhaitez. Cela rend la gestion des threads bien plus propre qu'en C ++. Vous êtes en contrôle total. Vous pouvez utiliserimmutable
et la transmission de messages pour communiquer entre les threads ou créer des variablesshared
et le faire à la manière C ++ avec des mutex et des variables de condition. Même cela est amélioré par rapport à C ++ avec l'introduction de synchronized (similaire à C # et Java). La situation de threading de D est donc bien meilleure que celle de C ++.Les modèles de D sont beaucoup plus puissants que les modèles de C ++, vous permettant de faire beaucoup plus, beaucoup plus facilement. Et avec l’ajout de contraintes de modèles, les messages d’erreur sont bien meilleurs qu’en C ++. D rend les templates très puissants et utilisables. Ce n'est pas un hasard si l'auteur de Modern C ++ Design est l'un des principaux collaborateurs de D. Je trouve que les modèles C ++ manquent sérieusement par rapport aux modèles D, ce qui peut être très frustrant lors de la programmation en C ++.
D possède une programmation contractuelle intégrée .
D possède un cadre de test unitaire intégré .
D prend en charge les codes unicode avec
string
(UTF-8),wstring
(UTF-16) etdstring
(UTF-32). Cela facilite la gestion de l’unicode. Et si vous souhaitez simplement utiliserstring
et ne vous souciez généralement pas de l'unicode, vous pouvez - bien que certaines notions de base relatives à Unicode soient utiles pour certaines fonctions de bibliothèque standard.La surcharge d'opérateurs de D est beaucoup plus agréable que celle de C ++, vous permettant d'utiliser une fonction pour surcharger plusieurs opérateurs en même temps. Un bon exemple en est le cas où vous devez surcharger les opérateurs arithmétiques de base et où leurs implémentations sont identiques, à l’exception de l’opérateur. Les mixins de chaînes en font un jeu d'enfant, vous permettant d'avoir une définition de fonction simple pour tous.
Les tableaux de D sont bien meilleurs que ceux de C ++. Non seulement sont-ils un type approprié avec une longueur, mais ils peuvent être ajoutés et redimensionnés. Les concaténer est facile. Et le meilleur de tous, ils ont trancher . Et c'est un avantage énorme pour un traitement efficace des tableaux. Les chaînes de caractères sont des tableaux de caractères en D, et ce n'est pas un problème (en fait, c'est génial!), Car les tableaux de D sont si puissants.
Je pourrais continuer encore et encore. Un grand nombre des améliorations apportées par D sont de petites choses (comme utiliser
this
des noms de constructeurs ou interdire si des instructions ou des corps de boucles où un point-virgule est tout leur corps), mais certaines d'entre elles sont assez volumineuses, et lorsque vous les additionnez, permet une expérience de programmation bien meilleure. C ++ 0x ajoute certaines des fonctionnalités de D dont C ++ était manquant (par exemple,auto
et lambdas), mais malgré toutes ses améliorations, il n'y aura toujours pas grand-chose qui soit objectivement meilleur en langage C ++ que D.Il ne fait aucun doute qu’il existe de nombreuses raisons subjectives de préférer l’une sur l’autre, et l’immaturité relative de la mise en œuvre de D peut parfois poser problème (même si elle s’est améliorée très rapidement récemment, surtout depuis que les dépôts ont été déplacés vers github ). et le manque de bibliothèques tierces peut poser problème (bien que le fait que D puisse facilement appeler des fonctions C - et dans une moindre mesure, des fonctions C ++ - atténue définitivement le problème). Mais ce sont des problèmes de qualité de mise en œuvre plutôt que des problèmes avec la langue elle-même. Et à mesure que la qualité des problèmes de mise en œuvre sera corrigée, il deviendra d'autant plus agréable d'utiliser D.
Donc, je suppose que la réponse courte à cette question est "très peu". D, en tant que langage, est généralement supérieur au C ++.
la source
Utilisation de la mémoire RAII et de la pile
D 2.0 n'autorise pas RAII sur la pile car il a supprimé la valeur du
scope
mot clé lors de l'allocation d'instances de classe sur la pile.Vous ne pouvez pas effectuer d'héritage de type valeur en D, ce qui vous oblige effectivement à effectuer une allocation de tas pour toute forme de RAII.
C'est-à-dire, sauf si vous utilisez
emplace
, mais c'est très pénible à utiliser, car vous devez allouer la mémoire à la main. (Je n'ai pas encore trouvé pratique à utiliseremplace
dans D.)la source
C ++ est bien meilleur pour vous forcer à être prolixe. Cela peut être meilleur ou pire à vos yeux, selon que vous aimiez l'inférence ou la verbosité.
Comparez la mémorisation au moment de l’exécution en C ++ :
avec la même chose en D:
Remarquez, par exemple, le surcroît de verbosité avec
template <typename ReturnType, typename... Args>
versus(F)
,Args...
versusArgs
,args...
versusargs
, etc.Pour le meilleur ou pour le pire, C ++ est plus détaillé.
Bien sûr, vous pouvez aussi le faire en D:
et ils sembleraient presque identiques, mais alors cela exigerait un
delegate
, alors que l'original acceptait n'importe quel objet appelable. (La version C ++ 0x nécessite unstd::function
objet, alors quoi qu'il en soit, ses entrées sont plus détaillées et plus restrictives ... ce qui peut être utile si vous aimez la verbosité, voire mauvais si vous ne l'aimez pas.)la source
Je ne connais pas grand chose à propos de D, mais beaucoup, beaucoup de programmeurs C ++ que je connais ne l'aiment pas du tout, et je dois personnellement en convenir - je n'aime pas le look de D et je ne le prendrai pas de plus près.
Afin de comprendre pourquoi D ne gagne pas en puissance, vous devez commencer par comprendre ce qui attire les gens vers C ++. En un mot, la raison numéro un est le contrôle. Lorsque vous programmez en C ++, vous avez un contrôle total sur votre programme. Voulez-vous remplacer la bibliothèque standard? Vous pouvez. Voulez-vous faire des lancers de pointeur dangereux? Vous pouvez. Voulez-vous violer const-correct? Vous pouvez. Voulez-vous remplacer l'allocateur de mémoire? Vous pouvez. Vous voulez copier la mémoire brute sans vous soucier de son type? Si tu le veux vraiment. Voulez-vous hériter de plusieurs implémentations? C'est ton enterrement. Enfer, vous pouvez même obtenir des bibliothèques de récupération de place, comme le collecteur Boehm. Ensuite, vous rencontrez des problèmes tels que les performances, qui suivent de près le contrôle: plus un programmeur a de contrôle, plus il peut optimiser son programme.
Voici quelques éléments que j'ai vus lors d'une petite recherche et de discussions avec quelques personnes qui l'ont essayée:
Hiérarchie de types unifiée. Les utilisateurs C ++ utilisent très rarement l'héritage, la plupart des programmeurs C ++ préfèrent la composition et les types ne doivent être liés par l'héritage que s'il existe une très bonne raison de le faire. Le concept d'objet viole fortement ce principe en liant tous les types. En outre, cela enfreint l'un des principes les plus fondamentaux du C ++: vous n'utilisez que ce que vous voulez. Ne pas avoir le choix d'hériter d'Object, et les coûts qui en découlent, vont tout à fait à l'encontre de ce que C ++ représente comme langage pour donner au programmeur le contrôle de son programme.
J'ai entendu parler de problèmes de fonctions et de délégués. Apparemment, D possède à la fois des fonctions et des délégués en tant que types de fonction appelables à l'exécution, et ils ne sont pas identiques, mais ils sont interchangeables ou ... quelque chose? Mon ami a eu pas mal de problèmes avec eux. C’est définitivement une dégradation de C ++, ce qui est déjà fait
std::function
et vous avez terminé.Ensuite, vous avez la compatibilité. D n'est pas particulièrement compatible avec C ++. Je veux dire, aucun langage n'est compatible avec le C ++, avouons-le, à l'exception de C ++ / CLI, qui est une sorte de triche, mais en tant que barrière à l'entrée, il faut le mentionner.
Ensuite, il y a d'autres choses. Par exemple, il suffit de lire l’entrée Wikipedia.
printf
est l’une des fonctions les moins sûres jamais conçues, dans la même famille que de gros problèmes comme celuigets
de l’ancienne bibliothèque C Standard. Si vous le recherchez sur Stack Overflow, vous trouverez de nombreuses questions relatives à son utilisation abusive. Fondamentalement,printf
est une violation de DRY- vous donnez le type dans la chaîne de format, puis vous le redonnez quand vous lui donnez un argument. Une violation de DRY dans laquelle, si vous vous trompez, de très mauvaises choses se produisent, par exemple si vous modifiez un typedef d'un entier 16 bits en un 32 bits. Il n’est pas non plus extensible du tout. Imaginez ce qui se passerait si tout le monde inventait ses propres spécificateurs de format. Les iostreams de C ++ peuvent être lents et leur choix d'opérateur peut ne pas être le plus grand. Leur interface peut utiliser le travail, mais leur sécurité est fondamentalement garantie, et DRY n'est pas violé et ils peuvent être étendus facilement. Ce n'est pas quelque chose dont on peut parlerprintf
.Pas d'héritage multiple. Ce n'est vraiment pas la méthode C ++. Les programmeurs C ++ s'attendent à avoir un contrôle total sur leur programme et le langage qui applique ce dont vous ne pouvez pas hériter enfreint ce principe. En outre, cela rend l'héritage (encore plus) fragile, car si vous passez d'un type d'interface à une classe parce que vous voulez fournir une implémentation par défaut ou quelque chose, tout le code de votre utilisateur est soudainement cassé. Ce n'est pas une bonne chose.
Un autre exemple est
string
etwstring
. En C ++, il est déjà très pénible de devoir convertir entre eux. Cette bibliothèque prend en charge l’Unicode. Cette ancienne bibliothèque C n’utilise queconst char*
la même fonction et doit écrire différentes versions de la même fonction en fonction du type d’argument de chaîne souhaité. Notamment, les en-têtes Windows, par exemple, contiennent des macros extrêmement irritantes pour faire face au problème, qui peuvent souvent interférer avec votre propre code. Ajouterdstring
à la combinaison ne fera qu'empirer les choses, car maintenant, au lieu de deux types de chaînes, vous devez en gérer trois. Avoir plus d'un type de chaîne va augmenter les problèmes de maintenance et introduire du code répétitif traitant des chaînes.Scott Meyers écrit:
L'isolation de thread appliquée par la langue n'est pas un avantage. Les programmeurs C ++ attendent un contrôle total de leurs programmes, et le langage qui force quelque chose n’est certainement pas ce que le médecin a prescrit.
Je vais aussi mentionner la manipulation de chaîne au moment de la compilation. D a la capacité d'interpréter le code D au moment de la compilation. Ce n'est pas un plus. Prenez en compte les énormes maux de tête causés par le préprocesseur relativement limité de C, bien connu de tous les programmeurs vétérans du C ++, puis imaginez à quel point cette fonctionnalité sera utilisée à mauvais escient. La possibilité de créer du code D au moment de la compilation est excellente, mais elle devrait être sémantique et non syntaxique.
De plus, vous pouvez vous attendre à un certain réflexe. D a garbage collection, que les programmeurs C ++ associeront à des langages tels que Java et C # qui lui sont assez directement opposés dans les philosophies, et les similitudes syntaxiques les rappelleront également. Ce n'est pas nécessairement objectivement justifiable, mais c'est quelque chose qu'il convient de noter.
Fondamentalement, il n'offre pas beaucoup de choses que les programmeurs C ++ ne peuvent pas déjà faire. Il est peut-être plus facile d'écrire un métaprogramme factoriel en D, mais nous pouvons déjà écrire des métaprogrammes factoriels en C ++. Peut-être qu'en D, vous pouvez écrire un traceur de rayons au moment de la compilation, mais personne ne veut vraiment le faire de toute façon. Comparé aux violations fondamentales de la philosophie C ++, ce que vous pouvez faire en D n’est pas particulièrement remarquable.
Même si ces problèmes ne sont que des problèmes à la surface, je suis presque sûr que le fait que D ne ressemble pas du tout à C ++ est probablement une bonne raison pour que de nombreux programmeurs C ++ ne migrent pas vers D. Peut-être que D doit faire un meilleur travail de publicité lui-même.
la source
std::function
et vous avez terminé. Pourquoi? Parce que vous avez également, par exemple, des pointeurs de fonction. C'est exactement la même chose dans D: les "fonctions" de D sont des pointeurs de fonction et les "délégués" de D sont identiques à ceux de C ++std::function
(sauf qu'ils sont intégrés). Il n'y a pas de «déclassement» où que ce soit - et il existe une correspondance 1: 1 entre eux, donc cela ne devrait pas du tout être déroutant si vous êtes familier avec C ++.Une des choses que j'apprécie en C ++ est la possibilité de documenter un argument de fonction ou une valeur renvoyée sous la forme d'une référence C ++ au lieu d'un pointeur, ce qui implique de prendre une non-
null
valeur.Version D:
Version C ++:
Pour être juste, vous pouvez vous rapprocher du C ++ en faisant
A
un Dstruct
et en marquant l'foo()
argument comme unref
(les classes sont des types de référence et les struct sont des types de valeur en D, similaires au C #).Je pense qu’il est prévu de créer un
NonNullable
modèle pour les classes sous la forme d’une bibliothèque D standard. Même si j'aime la brièveté de justType&
compare àNonNullable(Type)
, et préférerais non-nullable par défaut (rendre quelque chose commeType
etNullable(Type)
). Mais il est trop tard pour changer cela pour D et je m'éloigne maintenant du sujet.la source
ref
pour vous donner le même effet que celui de C ++&
. La seule différence majeure est queref
cela ne prendra pas de temps, même si c'estconst
.La chose la plus importante pour que C ++ "fasse mieux" que D est l’ interfaçage avec les bibliothèques existantes . Divers moteurs 3D, OpenCL et similaires. Comme D est nouveau, il y a beaucoup moins de bibliothèques à choisir.
Une autre différence importante entre le C ++ et le D réside dans le fait que le C ++ compte plusieurs fournisseurs indépendants sur le plan financier, mais à partir de 2014, le D n'en a pratiquement plus qu'un , l'équipe de deux personnes qui l'a créé. Il est intéressant de noter que le "principe de deuxième source" selon lequel les projets ne doivent jamais dépendre de la technologie, les composants, qui ne possèdent qu'un seul fournisseur, semblent également valables, même pour les logiciels.
À titre de comparaison, la première version de l'interprète Ruby a été écrite par l'inventeur de Ruby, le Yukihiro Matsumoto, mais l'interprète Ruby traditionnel de l'ère de 2014 a été écrit pratiquement à partir de rien par d'autres personnes. Par conséquent, Ruby peut être considéré comme un langage qui compte plusieurs fournisseurs indépendants du point de vue financier. D, d’autre part, peut être une technologie impressionnante, mais cela dépend des quelques développeurs qui la développent.
L’histoire de Java montre que, même si une technologie, dans ce cas-ci, a un fin financier simple mais unique, il existe un grand risque que la technologie soit essentiellement vidé, indépendamment de l’énorme base d’utilisateurs de l’entreprise. Une citation de la fondation Apache Software , où le CE signifie "Comité exécutif":
Oracle a fourni à la CE une demande de spécification et une licence Java SE 7 contradictoires, limitant considérablement la distribution d'implémentations indépendantes de la spécification et, surtout, interdisant la distribution d'implémentations open source indépendantes de la spécification.
En guise de note historique, on peut dire que les applets Java avaient une toile 3D accélérée matériellement avant le développement du WebGL HTML5. Le problème de la vitesse de démarrage des applets Java aurait pu être résolu si le projet Java avait été un projet de communauté, mais les dirigeants du seul financier du système Java, Sun Microsystems, n’avaient pas jugé suffisamment important de corriger l’implémentation Java. Le résultat final: une toile HTML5 par plusieurs fournisseurs en tant que "réplique du pauvre" des frameworks d'interface graphique Java (Swing, etc.). Il est intéressant de noter que côté langage, le langage de programmation Python présente les mêmes avantages que ceux promis par Java: écriture unique, exécution sur tous les serveurs, quel que soit le matériel, à condition que l’application Python ne soit pas compilée en code machine. Le Python est aussi vieux / jeune que le Java, mais contrairement au Java, il
Sommaire:
Lors de l'évaluation d'une technologie pour une utilisation en production, les propriétés les plus importantes des technologies sont les personnes qui la développent, le processus social, le lieu du développement et le nombre d'équipes de développement financièrement indépendantes.
Qu'il soit plus avantageux d'utiliser la technologie T1 par rapport à la technologie T2 dépend des vendeurs de technologies et si la technologie T1 permet de résoudre des problèmes liés au projet à moindre coût que la T2. Par exemple, si le problème du fournisseur unique était ignoré, alors, pour les systèmes d’information, Java serait une technologie «meilleure» que le C ++, car les fichiers binaires Java n’ont pas besoin de recompilation lors du déploiement sur du nouveau matériel et de la quantité de travail de développement logiciel lié à la gestion de la mémoire. est plus petit pour le Java que pour le C ++. Les projets développés de A à Z, par exemple les projets qui ne dépendent pas d'autres bibliothèques, pourraient être moins coûteux à développer en D qu'en C ++, mais d'un autre côté, le C ++ a plus d'un fournisseur et est donc moins risqué à long terme . (L’exemple Java, où Sun Microsystems était presque OK,
Une solution de contournement possible à certaines des limitations C ++
L’une des solutions possibles à certaines des limitations du C ++ consiste à utiliser un modèle de conception, dans lequel la tâche initiale est décomposée et les pièces sont "triées" (classées, regroupées, divisées, divisées en d’autres mots). même chose) à 2 classes: tâches liées à la logique de contrôle , où les modèles d’accès à la mémoire ne permettent pas la localité; traitement du signal comme tâches , où la localité est facilement réalisée. Les tâches "similaires" du traitement du signal peuvent être mises en oeuvre sous forme d'un ensemble de programmes de console relativement simplistes. Les tâches liées à la logique de contrôle sont toutes placées dans un seul script écrit en Ruby ou en Python ou dans un autre format, dans lequel le confort de développement logiciel a une priorité supérieure à la vitesse.
Pour éviter une initialisation coûteuse et une copie des données entre processus du système d'exploitation, l'ensemble de petites applications de console C ++ peut être implémenté en tant que programme C ++ unique démarré en tant que "servlet" par Ruby / Python / etc. scénario. Le Ruby / Python / etc. Le script ferme la servlet avant de quitter. Communication entre le "servlet" et le Ruby / Python / etc. Le script se déroule sur un canal nommé Linux ou un mécanisme similaire.
Si la tâche initiale ne se prête pas facilement à la division en pièces pouvant être classées dans les 2 classes susmentionnées, il peut être intéressant d'essayer de reformuler le problème afin que la tâche initiale change.
la source