Fonctionnalités C ++ «toute l'équipe»?

16

En C ++, des fonctionnalités comme les exceptions ont un impact sur l'ensemble de votre programme: vous pouvez soit les désactiver dans l'ensemble de votre programme , soit vous devez les gérer tout au long de votre code. Comme le dit un célèbre article sur le rapport C ++ :

Contre-intuitivement, la partie difficile du codage des exceptions n'est pas les lancers et les captures explicites. La partie vraiment difficile de l'utilisation des exceptions est d'écrire tout le code intermédiaire de telle manière qu'une exception arbitraire puisse se propager de son site de lancement à son gestionnaire, en arrivant en toute sécurité et sans endommager d'autres parties du programme en cours de route.

Étant donné que même newlève des exceptions, chaque fonction doit fournir une sécurité d'exception de base - à moins qu'elle n'appelle que des fonctions qui garantissent de ne lever aucune exception - à moins que vous ne désactiviez complètement les exceptions dans l'ensemble de votre projet .

Par conséquent, les exceptions sont une fonctionnalité «programme complet» ou «équipe complète», car elles doivent être comprises par tous les membres d'une équipe qui les utilisent. Mais toutes les fonctionnalités C ++ ne sont pas comme ça, pour autant que je sache.

Un exemple possible est que si je n'obtiens pas de modèles mais que je ne les utilise pas, je pourrai toujours écrire le C ++ correct - ou pas? Je peux même faire appel sortà un tableau d'entiers et profiter de son incroyable avantage de vitesse par rapport à. C qsort(car aucun pointeur de fonction n'est appelé), sans risquer de bugs - ou pas? Il semble que les modèles ne soient pas «toute l'équipe».

Existe-t-il d'autres fonctionnalités C ++ qui ont un impact sur le code qui ne les utilise pas directement et sont donc "toute l'équipe"? Je suis particulièrement intéressé par les fonctionnalités non présentes en C.

Mise à jour : je recherche en particulier des fonctionnalités où il n'y a pas de signe imposé par la langue dont vous devez être conscient. La première réponse que j'ai reçue a mentionné const-correctness, qui est également toute l'équipe, donc tout le monde doit en savoir plus; cependant, AFAICS, cela ne vous affectera que si vous appelez une fonction qui est marquée const, et le compilateur vous empêchera de l'appeler sur des objets non const, donc vous obtenez quelque chose pour Google. À des exceptions près, vous n'obtenez même pas cela; de plus, ils sont toujours utilisés dès que vous les utilisez new, les exceptions sont donc plus "insidieuses". Comme je ne peux pas formuler cela objectivement, j'apprécierai toute fonctionnalité de toute l'équipe.

Mise à jour 2 : au lieu de la fonctionnalité C ++, j'aurais dû écrire quelque chose comme "Fonction spécifique C ++", pour exclure des choses comme le multithreading qui s'appliquent à une grande quantité de langages de programmation traditionnels.

Annexe: Pourquoi cette question est objective (si vous vous demandez)

Le C ++ est un langage complexe, donc de nombreux projets ou guides de codage essaient de sélectionner des fonctionnalités C ++ "simples", et de nombreuses personnes essaient d'inclure ou d'exclure certaines selon des critères principalement subjectifs. Les questions à ce sujet sont régulièrement fermées à juste titre ici sur SO.

Ci-dessus, au lieu de cela, j'ai défini (aussi précisément que possible) ce qu'est une fonctionnalité de langage "toute l'équipe", donne un exemple (exceptions), ainsi que de nombreuses preuves à l'appui dans la littérature sur C ++, et demande des fonctionnalités pour toute l'équipe en C ++ au-delà des exceptions.

Le fait de savoir si vous devez utiliser les fonctionnalités de "toute l'équipe" ou s'il s'agit d'un concept pertinent peut être subjectif - mais cela signifie seulement que l'importance de cette question est subjective, comme toujours.

Blaisorblade
la source

Réponses:

11

Je proposerais la simultanéité comme une fonctionnalité «toute l'équipe».

Bien qu'il soit possible de concevoir le logiciel de telle sorte que seuls quelques experts doivent être conscients des problèmes de concurrence et que le reste de l'équipe puisse en tirer les avantages sans se soucier des complexités (comme vous pouvez le faire avec les modèles), en pratique, il le fait ne fonctionne pas de cette façon. En pratique, si vous disposez de plusieurs threads, vous devez analyser attentivement pour chaque variable que vous utilisez s'il existe des problèmes de concurrence potentiels avec cette utilisation.

Bart van Ingen Schenau
la source
Je suis d'accord que les threads sont de telles fonctionnalités pour toute l'équipe, bien qu'ils ne soient pas spécifiques à C ++. Cependant, il existe également d'autres interfaces vers la concurrence (non basées sur des threads), principalement dans d'autres langues, et quelques-unes permettent à la concurrence d'être bien mieux encapsulée (bien qu'il s'agisse toujours d'un sujet de recherche actuel dans les langages de programmation). C'est donc une question ouverte de savoir si cela s'applique à la concurrence en soi.
Blaisorblade
@Blaisorblade - C ++ 11 a présenté sa propre bibliothèque de threads, alors oui, il fait maintenant partie de C ++.
Michael Kohne du
@MichaelKohne: Je n'ai pas prétendu que C ++ ne supporte pas le multithreading. J'ai dit que les threads ne sont pas spécifiques au C ++, car de nombreux autres langages en ont. Je viens de noter que les problèmes décrits s'appliquent aux threads en tant qu'interface avec la concurrence.
Blaisorblade
Je dirais que «condition de concurrence» est un meilleur mot pour cette question centrale. Autrement dit, les programmeurs peuvent ne pas avoir besoin de travailler ou d'utiliser le framework de concurrence du tout, mais s'ils écrivent du code C ++ et que leur code peut être potentiellement appelé à partir de plusieurs threads, ils doivent alors réfléchir aux conditions de concurrence en général, dans tout leur code écrit.
rwong
Cela me rappelle une mauvaise communication avec un collègue qui s'est produite il y a des années. Un collègue a demandé à un autre collègue: est-ce (une fonction) thread-safe? L'autre collègue a répondu oui. Le collègue qui a demandé l'a ensuite utilisé à partir de plusieurs threads et a obtenu des résultats inattendus (il n'a pas planté, mais plusieurs opérations ont été appliquées au même objet). Il s'est avéré que le collègue qui a demandé n'avait pas le modèle mental de ce que signifie "thread-safe", et a pris la réponse comme "je peux faire ce que je veux."
rwong
10

La réponse évidente est la constjustesse: puisque const/ volatilequalification est contagieux, une fois qu'une partie du code a commencé à l'utiliser, chaque code appelant (directement ou indirectement) doit également être constcorrect, ou rejeter constexplicitement ness.

Comme pour les exceptions, cependant, c'est évidemment une bonne chose en fin de compte . Plus encore, car contrairement à la sécurité des exceptions, il est rigoureusement vérifié par le compilateur.

Konrad Rudolph
la source
2
De plus, const-correctness est transparent: il s'agit uniquement du type que vous donnez à une fonction (qui est toujours visible) et le compilateur vous hurlera si vous vous trompez. Je pensais à des choses plus opaques, où vous n'avez aucune idée que quelque chose ne va pas jusqu'à ce qu'il soit trop tard (et même alors, il sera difficile de le comprendre). Mais votre réponse est quand même intéressante, donc votée.
Blaisorblade
10

Pointeurs.

  • Le pointeur pointe-t-il vers la mémoire de la pile?
  • Le pointeur pointe-t-il vers la mémoire du tas?
  • Le pointeur pointe-t-il vers un seul objet?
  • Le pointeur pointe-t-il vers un tableau?
  • Le pointeur pointe-t-il vers un emplacement au milieu d'un tableau?
  • Le pointeur est-il valide?
  • Le pointeur est-il mutilé?
  • Quel code "possède" le pointeur?
  • Faut-il désallouer manuellement l'objet référencé? Si c'est le cas, comment?
Thomas Eding
la source
1
+1 spécifiquement en raison de la question sur la propriété du pointeur. Sans pointeurs intelligents, la propriété se propage vraiment dans toute l'équipe.
JKor
3

Une autre possibilité est la surcharge de l'opérateur. Une fois une partie de la base de code commence à bricoler avec tous les opérateurs surchargés a tendance à commencer à deviner seconde ce qu'ils travaillent objet exactement donné tout avec est en fait faire. Il ne se propage pas explicitement dans la base de code comme le font les exceptions et l'exactitude des const, mais c'est certainement quelque chose qui peut commencer à poser des problèmes si toute l'équipe n'est pas sur la même page quant au moment, à la manière et à la raison de son utilisation.

Evicatos
la source
1

Le seul en plus de l'exactitude constante (vu ci-dessus) qui vient à l'esprit est l'état de flux (ing). Si vous écrivez du code C ++ où vous utilisez des objets et des sous-objets et des hiérarchies d'objets, il est possible que vous souhaitiez envoyer ou recevoir des données de / vers l'opérateur du programme. Vous pouvez écrire des opérations de streaming simples qui se compileront et seront sémantiquement correctes ...

std::ostream& operator<< (std::ostream&, MyClass const&) {...}
std::istream& operator>> (std::istream&, MyClass&) {...}

... Mais une fois que vous l'avez fait, vous n'aurez plus aucune garantie que ce que vous essayez d'écrire (ou surtout, de lire) suit le même format que ce que le client vous envoie. Il y a trop de cas bizarres en cours avec des flux, encore pire si vous devez passer des flux ou des drapeaux de flux comme arguments le long de votre chaîne d'appels de fonction ... c'est ainsi que le streaming des classes est généralement implémenté. Le streaming peut donc être défini comme "insidieux" comme vous l'avez utilisé ci-dessus, ou peut-être même comme "viral" ( mais pas n'importe où au même degré que const-correctness ).

Avoir un membre au fond de votre hiérarchie de classe qui est un string? Surprise, le client envoie mieux un seul mot, sinon. Avez-vous des numéros que vous souhaitez sérialiser? Vous feriez mieux de vérifier, enregistrer et restaurer les indicateurs de flux à chaque profondeur d'appel de fonction, car vous ne savez jamais qui est l'idiot qui vient de définir son flux en sortie octale avant d'appeler votre fonction. Ou pire - qui vient d'appeler quelque chose comme setfillet a setwainsi rompu le formatage d'entrée / sortie de votre premier et uniquement de vos premiers membres intégraux car ces états ne se propagent pas . Oh et ne posons pas de questions sur les flux et l'internationalisation.

Il n'y a aucun avertissement dans la langue que vous diffusez de la bonne manière, ou de la mauvaise façon, ou même du tout . Code client demandé pour un flux à passer pour écrire la sauvegarde des données? Vous n'avez pas vraiment de moyen de savoir vers quoi pointe le flux /dev/null. ( D'un autre côté, vous pouvez revendiquer des vitesses de sauvegarde et des taux de compression incroyables de cette façon! )

Luis Machuca
la source