Salut,
J’imagine que tu parles de std::borrow::Cow
de Rust.
Classiquement, on a besoin de copier std::clone::Clone
un objet lorsqu’on désire conserver l’ancienne valeur (ce qui en Rust peut aussi bêtement servir à en garder l'ownership) mais effectuer un calcul dessus qui prend une valeur par référence (et donc la modifierait).
L’idée de Cow
(pour clone-on-write) est de déférer une copie au moment où on en a besoin. Le premier exemple de la doc est relativement parlant. La fonction abs_all
modifie potentiellement (mais pas forcément) le vecteur passé en référence pour avoir la valeur absolue élément par élément.
Le code donné en exemple est le suivant :
use std::borrow::Cow;
fn abs_all(input: &mut Cow<[i32]>) {
for i in 0..input.len() {
let v = input[i];
if v < 0 {
input.to_mut()[i] = -v;
}
}
}
let slice = [0, 1, 2];
let mut input = Cow::from(&slice[..]);
abs_all(&mut input);
let slice = [-1, 0, 1];
let mut input = Cow::from(&slice[..]);
abs_all(&mut input);
Sans Cow
, on pourrait implémenter de la façon suivante :
fn abs_all(input: &mut [i32]) {
for i in 0..input.len() {
let v = input[i];
if v < 0 {
input[i] = -v;
}
}
}
let slice = [0, 1, 2];
let mut input = slice.clone();
abs_all(&mut input);
let slice = [-1, 0, 1];
let mut input = slice.clone();
abs_all(&mut input);
Mais le problème avec ce deuxième code est que le premier clone ne sert à rien puisque la valeur n’est pas modifiée. On la dédouble donc en mémoire sans raison, ce qui prend du temps et de la place inutiles.
Cow
abstrait un besoin d’optimisation de copie : la donnée n’est copiée que si nécessaire. Dans l’exemple donné, on ne voit pas la différence parce que le vecteur est tout petit, mais si ton tableau prend par exemple 1 Go de RAM, éviter une copie inutile devient intéressant.