Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Как из String сделать &str (возникает ошибка времени жизни ссылки)

#rust


Написал функцию:

fn read_str<'a>() -> &'a str {
    let mut input = String::new();
    io::stdin().read_line(&mut input).ok();
    let output : &str = &input[..];
    &output
}


При компиляции возникает ошибка

src/main.rs:13:26: 13:31 error: `input` does not live long enough
src/main.rs:13     let output : &str = &input[..];
                                        ^~~~~
src/main.rs:10:30: 15:2 note: reference must be valid for the lifetime 'a as defined
on the block at 10:29...
src/main.rs:10 fn read_str<'a>() -> &'a str {
src/main.rs:11  let mut input = String::new();
src/main.rs:12  io::stdin().read_line(&mut input).ok();
src/main.rs:13     let output : &str = &input[..];
src/main.rs:14     &output
src/main.rs:15 }
src/main.rs:11:32: 15:2 note: ...but borrowed value is only valid for the block suffix
following statement 0 at 11:31
src/main.rs:11  let mut input = String::new();
src/main.rs:12  io::stdin().read_line(&mut input).ok();
src/main.rs:13     let output : &str = &input[..];
src/main.rs:14     &output
src/main.rs:15 }


Пробовал брать строку io::stdin().read_line(&mut input).ok(); в фигурные скобки,
дабы ограничить &mut, но это не помогает.
    


Ответы

Ответ 1



Вернуть из функции можно только ссылку на статический объект (с временем жизни 'static) или ссылку, которую вы получили во входных параметрах. Вы пытаетесь вернуть ссылку на объект созданный в стеке функции. После завершения функции все объекты в стеке будут уничтожены. Rust не позволит создать ссылку на объект, который она может пережить. Использование после освобождения (use after free) В вашем случае лучше всего вернуть String. Накладные расходы в этом случае невелики, так как почти вся информация внутри строки хранится в куче. Большинство проблем начинающих писать на Rust связаны с непониманием назначения различных типов указателей. Если не вдаваться в подробности, их там можно насчитать пять штук. Ссылки в Rust используются для передачи данных без передачи права владения. Например если у вас есть структура, в которой хранится строка: struct Person{ name:String } то выдавать информацию о ее содержимом лучше так: impl Person{ pub fn get_name(&self)->&str{ &self.name } } или можно вернуть копию строки: pub fn get_name_clone(&self)->String{ self.name.clone() } Но это приведет к дополнительным расходам на копирование строки. Расходы здесь возникают именно из-за копирования - вызова метода clone(), который создает вторую копию данных строки в куче, а не из-за того, что функция возвращает строку. Можно вернуть строку из структуры без копирования: pub fn get_name_own(self)->String{ self.name } Но после вызова этого метода исходный объект Person перестанет существовать, так как право владения было передано. Еще одна распространенная причина проблем - попытка хранить ссылки на другие объекты в структуре. Ссылки накладывают кучу ограничений на время жизни и мутабельность связанных объектов. Прежде чем это делать, стоит дважды подумать о возможности использования других типов указателей.

Комментариев нет:

Отправить комментарий