Je pense que la confusion viens du fait que les langages fonctionnels semblent (de ce que j'ai compris) favoriser la copie lors d'écriture et être optimisés pour ça. Ils masquent les mécanismes de bas niveau.
Oula non, malheureux ! :-P
Du moins tout dépend de ce que tu entends par copie. Ils ne favorisent pas du tout la copie, mais au contraire le partage de structures et cela pour deux raisons :
garantir l'immutabilité des structures quand on fait du fonctionnel pur;
économiser l'espace mémoire pour réaliser le premier point.
Par contre, effectivement, ils cachent les mécanismes bas niveau de gestion de la mémoire puisqu'il y a un GC (même si en OCaml il y a un module qui expose la représentation mémoire, mais dans ce cas il faut savoir ce que l'on fait comme dans des langages tels C ou C++ avec gestion manuelle). Il peut bien, par moment, y avoir « copie » qui en réalité est une « copie + suppression » (ce qui est en fait un « déplacement ») lorsque le GC passe, mais c'est tout.
C'est cet encodage par « partage » de structures que j'avais cru voir dans les shared_ptr. Cela étant, je me demande si ces derniers ne permettent pas de coder le même mécanisme, d'après ce que dit rewind dans ce commentaire :
puisqu'en C++, les struct et les class, c'est la même chose (à la différence que dans une struct, la visibilité par défaut est publique tandis que dans une class, la visibilité par défaut est privée).
Une liste en OCaml, comme dit précédemment, est une liste chaînée de type LIFO ce qui équivaut la structure C suivante :
À la différence de cette structure, les listes OCaml sont polymorphes ce qui n'est pas exprimable en C, mais de ce que j'ai compris devrait être exprimable en C++.
En OCaml une telle définition de structure s'écrirait :
(* un type polymorphe qui prend pour paramètre un type 'a quelconque *)type'aliste=(* soit la liste vide pour le cas du pointeur nul en C *)|Nil(* soit un élement de type 'a et une liste de même type *)|Consof'a(* head *)*'aliste(* tail *)
Pour montrer qu'il y a bien partage en mémoire et non copie, je vais l'illustrer avec l'utilisation de deux prédicats d'égalité = et ==. Le premier est une égalité structurelle et parcourt les deux structures pour vérifier si elles représentent la même chose, bien qu'occupant des zones mémoires différentes; tandis que le second est une égalité physique et vérifie simplement les adresses mémoires. Le second répond en temps constant, tandis que le premier peut même rentrer dans une boucle infinie et ne jamais terminer.
(* deux listes structurellement identiques *)letl=[1;2]andl'=[1;2];;vall:intlist=[1;2]vall':intlist=[1;2](* elles n'occupent pas la même zone mémoire mais représente la même liste *)l=l';;-:bool=truel==l';;-:bool=false(* maintenant je crée deux liste en ajoutant un élément en tête de l *)letl1=3::landl2=4::l;;vall1:intlist=[3;1;2]vall2:intlist=[4;1;2](* elles sont bien différentes à tout point de vue *)l1=l2;;-:bool=falsel1==l2;;-:bool=false(* mais leurs queues sont identiques à tout point de vue *)List.tll1;;-:intlist=[1;2]List.tll1=List.tll2;;-:bool=trueList.tll1==List.tll2;;-:bool=true(* en revanche si je pars de la liste l' *)letl1'=3::l';;vall1':intlist=[3;1;2]l1=l1';;-:bool=truel1==l1';;-:bool=falseList.tll1==List.tll1';;-:bool=false
C'est pour cela que je me demande si les shared_ptr, au lieu d'être vus comme une zone mémoire partagée dans laquelle plusieurs objets peuvent écrire, ne peuvent être utilisés pour définir des structures vérifiant ces conditions :
garantir l'immutabilité des structures ;
économiser l'espace mémoire pour réaliser le premier point.
L'immutabilité d'une structure est une propriété très intéressante et qui permet de raisonner bien plus facilement sur le code : c'est pour cela qu'en fonctionnel pur elles sont toutes ainsi faites.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
[^] # Re: Donc pour résumer...
Posté par kantien . En réponse à la dépêche C++17, Genèse d’une version mineure. Évalué à 4.
Oula non, malheureux ! :-P
Du moins tout dépend de ce que tu entends par copie. Ils ne favorisent pas du tout la copie, mais au contraire le partage de structures et cela pour deux raisons :
Par contre, effectivement, ils cachent les mécanismes bas niveau de gestion de la mémoire puisqu'il y a un GC (même si en OCaml il y a un module qui expose la représentation mémoire, mais dans ce cas il faut savoir ce que l'on fait comme dans des langages tels C ou C++ avec gestion manuelle). Il peut bien, par moment, y avoir « copie » qui en réalité est une « copie + suppression » (ce qui est en fait un « déplacement ») lorsque le GC passe, mais c'est tout.
C'est cet encodage par « partage » de structures que j'avais cru voir dans les
shared_ptr. Cela étant, je me demande si ces derniers ne permettent pas de coder le même mécanisme, d'après ce que dit rewind dans ce commentaire :Une liste en OCaml, comme dit précédemment, est une liste chaînée de type LIFO ce qui équivaut la structure C suivante :
À la différence de cette structure, les listes OCaml sont polymorphes ce qui n'est pas exprimable en C, mais de ce que j'ai compris devrait être exprimable en C++.
En OCaml une telle définition de structure s'écrirait :
Pour montrer qu'il y a bien partage en mémoire et non copie, je vais l'illustrer avec l'utilisation de deux prédicats d'égalité
=et==. Le premier est une égalité structurelle et parcourt les deux structures pour vérifier si elles représentent la même chose, bien qu'occupant des zones mémoires différentes; tandis que le second est une égalité physique et vérifie simplement les adresses mémoires. Le second répond en temps constant, tandis que le premier peut même rentrer dans une boucle infinie et ne jamais terminer.C'est pour cela que je me demande si les
shared_ptr, au lieu d'être vus comme une zone mémoire partagée dans laquelle plusieurs objets peuvent écrire, ne peuvent être utilisés pour définir des structures vérifiant ces conditions :L'immutabilité d'une structure est une propriété très intéressante et qui permet de raisonner bien plus facilement sur le code : c'est pour cela qu'en fonctionnel pur elles sont toutes ainsi faites.
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.