部分的な初期化
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::mem::MaybeUninit; fn main() { // let mut buf = [0u8; 2048]; let mut buf = [const { MaybeUninit::<u8>::uninit() }; 2048]; let external_data = b"Hello, Rust!"; let len = external_data.len(); for (dest, src) in buf.iter_mut().zip(external_data) { dest.write(*src); } // SAFETY: `buf` のうちちょうど `len` バイトを UTF-8 テキストで初期化した let text: &str = unsafe { let ptr: *const u8 = buf.as_ptr().cast::<u8>(); let init: &[u8] = std::slice::from_raw_parts(ptr, len); std::str::from_utf8_unchecked(init) }; println!("{text}"); }
このコードは、何らかの外部ソースからデータを受信する状況をシミュレートしています。
外部ソースからバッファへバイト列を読み込むとき、通常は受信するバイト数がわかりません。MaybeUninit<T> を使うと、冗長な初期化パスのコストを払うことなく、バッファを一度だけ確保できます。
標準的な構文(buf = [0u8; 2048])で配列を作成すると、バッファ全体がゼロで埋められます。MaybeUninit<T> は、領域は確保するものの、まだそのメモリには触れないようコンパイラに伝えます。
Q: このコードスニペットのどの部分が .assume_init() と同様の役割を果たしていますか? A: ポインタのキャストと暗黙の読み出しです。
配列全体に対して assume_init() を呼び出すことはできません。ほとんどの要素が未初期化のままなので、それは不健全です。代わりに、ポインタを *const MaybeUninit<u8> から *const u8 にキャストし、初期化済みの部分だけを対象とするスライスを構築します。