動的メモリ上の型に見られる leak 系メソッドについて。
これらのメソッドは動的に取得した領域を、プログラム終了まで固定領域として使用し続けるのに用いる。参照がまだ生きている点を除けば、これは名前の由来のメモリリークと似た状況である (一応、戻そうと思えば Box::from_raw 関数などで再び解放が可能になる)。
以下は std クレート内の該当メソッドの一覧である。
どのメソッドも self を消費して可変参照を戻す。
Box<T, A> |
fn leak<'a>(self) -> &'a mut T where A: 'a |
|---|---|
Vec<T, A> |
fn leak<'a>(self) -> &'a mut [T] where A: 'a |
String |
fn leak<'a>(self) -> &'a mut str |
OsString |
fn leak<'a>(self) -> &'a mut OsStr |
PathBuf |
fn leak<'a>(self) -> &'a mut Path |
以下では、型パラメタ T に対応する既定値への参照を取得している。
use std::any::{Any, TypeId};
use std::collections::BTreeMap;
use std::sync::Mutex;
pub fn default_ref<T>() -> &'static T
where
T: Any + Default + Send + Sync + ?Sized,
{
static MAP: Mutex<BTreeMap<TypeId, &'static (dyn Any + Send + Sync)>> =
Mutex::new(BTreeMap::new());
MAP.lock()
.unwrap()
.entry(TypeId::of::<T>())
.or_insert_with(|| Box::leak(Box::new(T::default())))
.downcast_ref()
.unwrap()
}
use std::any::{Any, TypeId};
use std::cell::RefCell;
use std::collections::btree_map::BTreeMap;
pub fn default_ref<T>() -> &'static T
where
T: Any + Default + ?Sized,
{
thread_local! {
static MAP: RefCell<BTreeMap<TypeId, &'static dyn Any>> =
RefCell::new(BTreeMap::new());
}
MAP.with(|x| {
x.borrow_mut()
.entry(TypeId::of::<T>())
.or_insert_with(|| Box::leak(Box::new(T::default())))
.downcast_ref()
.unwrap()
})
}