Rustの面白い関数にstd::mem::forgetがあります。
Rustには値がスコープ外になった時の後処理を記述できるDropというtraitがあり、 リソースのリーク漏れを防いでくれます。
Dropのおかげでmallocしてfreeしたりfileをopenしてcloseするなどの処理は自分で書く必要がないし忘れる事もないわけです。
{
let heap_memory = Box::new(1);//heapにメモリを確保
}//scopeから外れたので自動でメモリを解放
forget関数はdrop処理を無効にし意図的にリソース漏れをさせる関数です。
{
let heap_memory = Box::new(1);//heapにメモリを確保
std::mem::forget(heap_memory);
}//メモリリーク!!
こんな関数何の役に立つのかと思いますが、 特定のケースでは有効です。
例えば二つの値を交換するswap関数です。
use std::mem;
use std::ptr;
fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
let mut temp: T = mem::uninitialized();
//tempに一端値を退避して交換
ptr::copy_nonoverlapping(x, &mut temp, 1);
ptr::copy_nonoverlapping(y, x, 1);
ptr::copy_nonoverlapping(&temp, y, 1);
}
}
let mut x = Box::new(1);
let mut y = Box::new(2);
swap(&mut x, &mut y);
println!("x = {}, y = {}", x, y)// x = 2, y = -46065496
tempとyが同じものを指しているため 型TがDropを実装している場合 swap関数を抜けた後にtempと一緒にyまでdropされてしまいます。
tempの解放処理はしたくありません。
このような場合にforgetが有用です
use std::mem;
use std::ptr;
fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
let mut temp: T = mem::uninitialized();
//tempに一端値を退避して交換
ptr::copy_nonoverlapping(x, &mut temp, 1);
ptr::copy_nonoverlapping(y, x, 1);
ptr::copy_nonoverlapping(&temp, y, 1);
//tempの解放処理はしない
mem::forget(temp);
}
}
let mut x = Box::new(1);
let mut y = Box::new(2);
swap(&mut x, &mut y);
println!("x = {}, y = {}", x, y)// x = 2, y = 1
Rust面白いですね。!