История вопроса:
По сравнению с нативными языками (C/C++), Rust строит безопасную работу со строками за счет строгого разделения ссылочных (&str) и владельческих (String) типов. Это избавляет от большинства ошибок, связанных с некорректной памятью, выходом за пределы буфера и double-free.
Проблема:
В отличие от взрослых GC-языков, где любая строка живет в управляемой памяти, в Rust надо четко понимать, кто владеет строкой, как долго она живет, и как не получить dangling reference после модификаций. Работа с UTF-8-строками требует аккуратности при индексации и изменении.
Решение:
В Rust String — это изменяемая, heap-аллоцированная строка, которая владеет своим содержимым. &str — это неизменяемая ссылка на последовательность байт с гарантией UTF-8. При необходимости можно безопасно конвертировать (&str -> String и обратно) с помощью методов std.
Пример кода:
fn main() { let owned: String = String::from("Rust"); let borrowed: &str = &owned; let primitive: &str = "Hello"; // литерал всегда &str // Конвертация &str -> String let s: String = primitive.to_string(); // Конвертация String -> &str let st: &str = &s; println!("{} {} {} {}", owned, borrowed, primitive, st); }
Ключевые особенности:
&'static str, а не StringПочему нельзя индексировать строку как s[1] или s[i]?
Rust строки в UTF-8, поэтому индексация недоступна напрямую: s[i] не возвращает i-й символ, а иногда приводит к panic при доступе к некорректной границе байтов. Вместо этого используйте методы .chars().nth(i) или .get(start..end).
Можно ли безопасно модифицировать &str?
Нельзя — &str всегда immutable slice. Для модификаций делайте to_owned/to_string, либо используйте String/Vec<u8>.
Чем принципиально отличается String::from("abc") от "abc".to_string()?
Эти варианты эквивалентны по результату, оба создают String с копированием данных из &str. Разница лишь в стиле: например, to_string реализован через трейт ToString, а String::from контрастнее выражает intent "создать владение".
Функция принимала String и делала ненужное копирование строки внутри (clone), затем писала slice в другой функции, забывая продлить срок жизни источника. Result: dangling reference & crash.
Плюсы:
Минусы:
Функция принимает &str, если нужны модификации — внутри вызывает .to_string(), снаружи вся логика остается "zero copy". Сроки жизни под контролем, ни одной лишней аллокации.
Плюсы:
Минусы: