4.6 Copie et partage
Le problème de la copie et du partage consiste à faire une choix important dans la sémantique des opérations.
Dans le monde mathématique les objets sont immuables (le nombre 6 ne peut pas devenir 12)
Dans un système informatique les objets sont mutables, leur valeur peut changer.
Si deux variables font référence au même objet, une modification de cet objet change simultanément la valeur
référencée par ces variables, on dira alors que ces variables se partagent un objet.
Exemple :
List a ;
vide(a) ;
b = cons ( a, 'toto')
c = cons ( b, 'maman')
D'après la spécification de cons, le résultat de b = cons ( a, 'toto') est un nouvel objet de Liste tel que sa tête vaut 'toto'
et son reste vaut a.
Cette opération introduit donc un partage de structure entre b et a, puisque le reste de b est l'objet a.
De même c = cons ( b, 'maman') introduit un partage entre c et b.
La liste c a pour contenu ('maman' ('toto' vide)), si maintenant nous faisons vide(b), c deviendra ('maman' vide).
Le partage de structure n'est donc pas sans danger car une modification de b modifie également c sans qu'il y ait accès
explicite à c.
Si l'on veut éviter le partage de structure on peut recourir à la copie.
La copie d'un objet x consiste à fabriquer un nouvel objet y distinct de x mais portant la même valeur.
Il faut bien entendu faire des copies de tous les objets qui composent x.
Dans le cas des listes, si x a pour reste la liste x' et pour tête l'objet o, il faut commencer par faire une copie de x' en y' et
une copie de o en o', puis construire y avec o' et y'. La copie de x' peut elle-même nécessiter la copie de son reste, et ainsi
de suite.
Méthode copie (o suppose qu'il existe une méthode copie qui effectue une copie d'un élément de la liste)
Element copieElement ;
Liste result ; vide(result) ;
Liste aCopier = self ;
While not (estVide(aCopier))
copieElement = copie(aCopier.tete) ;
result = cons (copieElement, result) ;
aCopier = aCopier.reste ;
}
return result ; //la liste a été inversée
Si le partage présente certains dangers, il évite par contre de recopier inutilement des parties de liste.
Par exemple,
pour accéder au second élément de c on fera:
second := (c.reste).tete.
S'il y a partage de structure cette opération est très simple. Si au contraire la méthode reste recopie tous les éléments de
c sauf la tête pour créer une nouvelle liste, le simple accès au second élément de c devient très coûteux lorsque c est
longue.
|