From 2f83d2104d3895fe017c4885db1bebbd4311f562 Mon Sep 17 00:00:00 2001 From: Orestis Malaspinas <orestis.malaspinas@hesge.ch> Date: Tue, 6 Nov 2018 14:54:20 +0100 Subject: [PATCH] ajout smart pointers --- index.md | 1 + smart_pointers.md | 114 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 smart_pointers.md diff --git a/index.md b/index.md index c77137e..391cc33 100644 --- a/index.md +++ b/index.md @@ -20,6 +20,7 @@ sansfont: Sans Serif - [4.1 Commentaires](commentaires.html). - [4.2 Gestion d'erreurs](errors.html). - [6.1 Méthodes](methods.html). +- [6.2 Pointeurs intelligents](smart_pointers.html). - [6.2 Collections: String, Vector, HashMap](collections.html). - [7.1 Tests](tests.html). - [8.1 Itérateurs](iterators.html). diff --git a/smart_pointers.md b/smart_pointers.md new file mode 100644 index 0000000..b30e723 --- /dev/null +++ b/smart_pointers.md @@ -0,0 +1,114 @@ +--- +title: Cours de programmation séquentielle +subtitle: Pointeurs intelligents +author: Orestis Malaspinas +sansfont: Sans Serif +--- + +# Pointeurs + +## Généralités + +- Un **pointeur** est une variable qui contient une adresse mémoire. +- Cette adresse **pointe** vers des données. + +{width=50%} + +- Question: Quel type de pointeur avons-nous déjà rencontré? + - Réponse: La référence. + +## Smart pointers + +- Un **pointeur intelligent** est un type abstrait qui rajoute des fonctionnalités au poiteur standard. + - Management automatique de la mémoire. + - Vérification de limites. +- En particulier, ils permettent la désallocation de la mémoire de manière automatique: + - On peut avoir plusieurs pointeurs sur un espace mémoire. + - Quand le dernier pointeurs est détruit, l'espace mémoire est désalloué. + - Permet d'empêcher les fuites mémoires. +- Il existe différents types: + - Un poiteur unique est le propriétaire de ses données (quand il est détruit les données aussi). + - On compte le nombre de références sur des données, quand ce nombre tombe à zéro on détruit tout. + +## En Rust + +- Exemples: + - `Vec<T>`{.rust}, `String`{.rust}: ces types possèdent de la mémoire et la manipule eux-mêmes. +- Les pointeurs intelligent doivent implémenter deux traits: + - `Deref`{.ruist}: comment on déréférence le pointeur. + - `Drop`{.rust}: comment on détruit le pointeur. +- Les trois cas les plus typiques (il y en a d'autres): + - `Box<T>`{.rust} pointeur unique qui alloue des données sur la pile. + - `Rc<T>`{.rust} "reference counted" type, qui permet de partager la propriété. + - `Ref<T>`{.rust} et `RefMut<T>`{.rust} qui permet d'imposer les règles de propriété à l'exécution plutôt qu'à la compilation. + +# Le type `Box<T>`{.rust} + +## Généralités + +- Utile pour stocker des données sur le tas. +- La seule chose stockée sur la pile est le pointeur sur les données du tas. +- Cas typiques d'utilisation: + - Quand la taille d'un type est inconnu à la compilation. + - Quand on veut transférer la propriété de grandes quantité de données mais s'assurer que les données ne seront pas copiées (juste le pointeur). + +## Utilisation + +<pre><code data-trim="hljs rust" class="lang-rust"> +fn main() +{ + let num = Box::new(10); + println!("num = {}", num); // déréférenciation automatique + println!("num = {}", *num); // déréférenciation explicite + + let x = 10; + // seule la déréférenciation explicite marche + println!("Is {} equal to {}?. Answer: {}", num, x, *num == x); + + let y = &x; + // La seule différence est qu'ici nous avons une référence + println!("Is {} equal to {}?. Answer: {}", y, x, *y == x); +} +</code></pre> + +- Dans l'appel de fonctions/méthodes la déréférenciation se fait automatiquement. +- Sinon elle doit être explicite. + +## Car pratique: la liste chaînée + +- Rust doit connaître la taille d'un type **à la compilation**. +- Ici nous avons à faire à un type **récursif**: sa taille est potentiellement infinie. + +<pre><code data-trim="hljs rust" class="lang-rust"> +enum List { + Elem(i32, List), + Nil, +} + +use List::{Elem, Nil}; + +fn main() +{ + let list = Elem(1, Elem(2, Elem(3, Nil))); +} +</code></pre> + +## Car pratique: la liste chaînée + +- Avec un `Box<T>`{.rust} sa taille est connue. + +<pre><code data-trim="hljs rust" class="lang-rust"> +#[derive(Debug)] +enum List { + Elem(i32, Box<List>), + Nil, +} + +use List::{Elem, Nil}; + +fn main() +{ + let list = Elem(1, Box::new(Elem(2, Box::new(Elem(3, Box::new(Nil)))))); + println!("{:?}", list); +} +</code></pre> -- GitLab