LoginSignup
19
11

More than 5 years have passed since last update.

Rustのforget関数

Posted at

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面白いですね。!

参考 forgetのドキュメント

19
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
11