MaybeUninit.write() と代入

// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0

use std::mem::MaybeUninit;

fn main() {
    let mut buf = MaybeUninit::<String>::uninit();

    // 初期化
    buf.write(String::from("Hello, Rust!"));

    // 上書き
    buf.write(String::from("Hi again"));

    // 代入では MaybeUninit の値全体が置き換えられる。
    buf = MaybeUninit::new(String::from("Goodbye"));

    // 内側の値がドロップされることを確認
    let _ = unsafe { buf.assume_init() };
}

内側の値を置き換えると、drop のセマンティクスがほとんどの型と異なるため、 メモリリークを引き起こす可能性があります。MaybeUninit<T> はその T のデストラクタを呼び出しません。

MaybeUninit::write()ptr::write を使います。これは古い内容を読み取ったり ドロップしたりせずに、その場でメモリを初期化します。メモリが未初期化である 可能性があるときには、これはまさに望ましい動作ですが、そこにすでに有効な値が 入っていた場合はリークすることも意味します。

代入、たとえば buf = MaybeUninit::new(value) は、MaybeUninit 全体を 置き換えます。古い MaybeUninit はムーブされたあとにドロップされますが、 MaybeUninit には T 用のデストラクタがないため、内側の値はドロップされません。 古いスロットに初期化済みの値が入っていた場合、それは write() と同様に リークします。

通常の drop 動作が必要な場合は、assume_init または関連するメソッドのいずれかを使って、 その値が初期化済みであることを Rust に伝える必要があります。