En C, il n'est pas nécessaire de transtyper un void *
vers un autre type de pointeur, il est toujours promu en toute sécurité. Cependant, en C ++, ce n'est pas le cas. Par exemple,
int *a = malloc(sizeof(int));
fonctionne en C, mais pas en C ++. (Remarque: je sais que vous ne devriez pas utiliser malloc
en C ++, ou d'ailleurs new
, et que vous devriez plutôt préférer les pointeurs intelligents et / ou la STL; cela est demandé uniquement par curiosité.) Pourquoi la norme C ++ n'autorise-t-elle pas cette conversion implicite, alors que la norme C le fait?
c++
language-features
wolfPack88
la source
la source
long *a = malloc(sizeof(int));
Oups, quelqu'un a oublié de changer un seul type!sizeof(*a)
place.malloc
ne peut pas retourner un pointeur sur le type alloué.new
si C ++ renvoie un pointeur sur le type alloué, le code C ++ correctement écrit n'aura jamais devoid *
s à convertir.void
, C non . Lorsque ce mot-clé / idée a été ajouté à C, ils l'ont changé pour l'adapter aux besoins de C. Ce fut peu de temps après les types de pointeur ont commencé à être vérifiés à tout . Voyez si vous pouvez trouver la brochure de description K&R C en ligne, ou une copie vintage d'un texte de programmation C comme le C Primer de Waite Group . ANSI C était plein, de fonctionnalités rétroportées ou inspirées par C ++, et K&R C était beaucoup plus simple. Il est donc plus correct que C ++ ait étendu C tel qu'il existait à l'époque, et que le C que vous connaissez a été supprimé de C ++.Réponses:
Parce que les conversions de types implicites sont généralement dangereuses et que C ++ adopte une position de sécurité plus sûre que C.
C autorise généralement les conversions implicites, même si la plupart des chances sont que la conversion est une erreur. C'est parce que C suppose que le programmeur sait exactement ce qu'il fait, et sinon, c'est le problème du programmeur, pas le problème du compilateur.
C ++ interdira généralement les choses qui pourraient potentiellement être des erreurs et vous obligera à indiquer explicitement votre intention avec un transtypage de type. C'est parce que C ++ essaie d'être convivial pour les programmeurs.
Vous vous demandez peut-être pourquoi il est convivial alors qu'il vous oblige à taper davantage.
Eh bien, vous voyez, toute ligne de code donnée, dans n'importe quel programme, dans n'importe quel langage de programmation, sera généralement lue beaucoup plus de fois qu'elle ne sera écrite (*). Ainsi, la facilité de lecture est beaucoup plus importante que la facilité d'écriture. Et lors de la lecture, le fait de faire ressortir des conversions potentiellement dangereuses au moyen de transtypages explicites aide à comprendre ce qui se passe et à avoir un certain niveau de certitude que ce qui se passe est en fait ce qui était censé se produire.
En outre, l'inconvénient d'avoir à taper la distribution explicite est trivial par rapport à l'inconvénient d'heures après des heures de dépannage pour trouver un bogue qui a été causé par une affectation erronée dont vous auriez pu être averti, mais qui ne l'ont jamais été.
(*) Idéalement, il ne sera écrit qu'une seule fois, mais il sera lu chaque fois que quelqu'un devra le réviser pour déterminer sa pertinence pour la réutilisation, et chaque fois qu'un dépannage est en cours, et chaque fois que quelqu'un doit ajouter du code à proximité, puis à chaque fois qu'il y a un dépannage du code à proximité, etc. Cela est vrai dans tous les cas, sauf pour les scripts "écrire une fois, exécuter, puis jeter", et il n'est donc pas étonnant que la plupart des langages de script aient une syntaxe qui facilite la facilité d'écriture avec un mépris total pour la facilité de lecture. Avez-vous déjà pensé que Perl est complètement incompréhensible? Tu n'es pas seul. Considérez ces langues comme des langues "en écriture seule".
la source
void*
sont plus dangereux en C ++, car avec la façon dont certaines fonctionnalités OOP sont implémentées en C ++, le pointeur vers le même objet peut avoir une valeur différente selon le type de pointeur.Voici ce que dit Stroustrup :
Il présente ensuite un exemple de la façon dont le vide * peut être dangereux et dit:
Enfin, il note:
Il va dans beaucoup plus de détails à ce sujet dans The Design and Evolution of C ++ .
La réponse se résume donc à: le concepteur de langage pense qu'il s'agit d'un modèle dangereux, et l'a donc rendu illégal et a fourni d'autres moyens d'accomplir ce à quoi le modèle était normalement utilisé.
la source
malloc
exemple, il convient de noter quemalloc
(évidemment) n'appellera pas un constructeur, donc s'il s'agit d'un type de classe pour lequel vous allouez de la mémoire, être implicitement converti en type de classe serait trompeur.C'est toujours promu, oui, mais pas en toute sécurité .
C ++ désactive ce comportement précisément parce qu'il tente d'avoir un système de type plus sûr que C, et ce comportement n'est pas sûr.
Considérez en général ces 3 approches de conversion de type:
Eh bien, 1 est moche et un obstacle pratique pour faire quoi que ce soit, mais pourrait vraiment être utilisé là où un grand soin est nécessaire. C a à peu près opté pour 2, qui est plus facile à implémenter, et C ++ pour 3, qui est plus difficile à implémenter mais plus sûr.
la source
Par définition, un pointeur vide peut pointer vers n'importe quoi. Tout pointeur peut être converti en un pointeur vide et ainsi, vous pourrez reconvertir en arrivant à la même valeur exacte. Cependant, les pointeurs vers d'autres types peuvent avoir des contraintes, telles que des restrictions d'alignement. Par exemple, imaginez une architecture où les caractères peuvent occuper n'importe quelle adresse mémoire, mais les entiers doivent commencer sur des limites d'adresse égales. Dans certaines architectures, les pointeurs entiers peuvent même compter 16, 32 ou 64 bits à la fois afin qu'un char * puisse en fait avoir un multiple de la valeur numérique de int * tout en pointant vers le même endroit en mémoire. Dans ce cas, la conversion à partir d'un vide * arrondirait en fait des bits qui ne peuvent pas être récupérés et ne sont donc pas réversibles.
En termes simples, le pointeur vide peut pointer vers n'importe quoi, y compris des choses vers lesquelles d'autres pointeurs peuvent ne pas être capables de pointer. Ainsi, la conversion en pointeur vide est sûre mais pas l'inverse.
la source