Skip to content

String::into_boxed_str

String methods · Strings

Level: reference · for working programmers

One line: Consumes the String and returns a Box<str> — shrinks to fit and drops the capacity field, saving eight bytes per value.

pub fn into_boxed_str(self) -> Box<str>

Stable since 1.4.0.

String is three words: pointer, length, capacity. Box<str> is two — it cannot grow, so it does not need to remember how much room it has. For a value stored once and read many times, that is 8 bytes saved on a 64-bit machine, and in a collection of a million it is 8 MB.

It shrinks first, so any spare capacity is returned to the allocator; that may reallocate and copy.

The trip back is str::into_string, also O(1) — the same allocation, given a capacity field again.

The trade is growth. Use it for finished text — interned names, parsed configuration, map keys — and keep String for anything still being built.

Example

string_into_boxed_str.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    let mut s = String::with_capacity(64);
    s.push_str("finished");
    println!("String   len {} capacity {}", s.len(), s.capacity());

    let boxed: Box<str> = s.into_boxed_str();
    println!("Box<str> len {}", boxed.len());

    // Two words instead of three.
    println!("String {} bytes / Box<str> {} bytes",
             std::mem::size_of::<String>(), std::mem::size_of::<Box<str>>());

    // The spare capacity was returned on the way.
    let back = boxed.into_string();
    println!("back    len {} capacity {}", back.len(), back.capacity());

    // Everything a &str can do still works; growing does not.
    let names: Vec<Box<str>> = ["ada", "grace"].iter().map(|s| (*s).into()).collect();
    println!("{:?}", names.iter().map(|n| n.to_uppercase()).collect::<Vec<String>>());
}

Verified output of string_into_boxed_str.rs — regenerated by tools/run_examples.py, never hand-typed.

String   len 8 capacity 64
Box<str> len 8
String 24 bytes / Box<str> 16 bytes
back    len 8 capacity 8
["ADA", "GRACE"]

See also

String::into_boxed_str in the standard library ↗

Po polsku

String zajmuje trzy słowa maszynowe — wskaźnik, długość i pojemność — a Box<str> dwa, bo skoro nie może rosnąć, to nie musi pamiętać, ile ma jeszcze wolnego miejsca. Wyjście przykładu pokazuje to wprost: 24 bajty kontra 16, czyli osiem bajtów na wartość, a przy milionie wartości w kolekcji osiem megabajtów. Konwersja nie jest przy tym darmowa — najpierw wykonuje shrink_to_fit, więc nadmiarowa pojemność wraca do alokatora (capacity 64capacity 8), co może oznaczać realokację i przepisanie bajtów; płacisz raz, a oszczędzasz stale. Wymieniasz zatem możliwość wzrostu na miejsce na stercie, więc Box<str> pasuje do tekstu skończonego — nazw, sparsowanej konfiguracji, kluczy w mapie — a wszystko, co jeszcze budujesz, zostaje Stringiem; droga powrotna przez into_string() jest tania.

Szukaj po polsku: Box<str> a String · rozmiar typu w pamięci · oszczędzanie pamięci na stercie · rust into_boxed_str · rust Box<str> vs String memory