Rust函数返回Vec<&str>时生命周期错误的解决方法
Vec<&str>结果? 初始实现代码
use std::fs; fn read_input_file(input_file: String, path_list: &mut Vec<&str>) { let output_file = fs::read_to_string(input_file).expect("Should have been able to read the file"); *path_list = output_file.split('\n').collect::<Vec<&str>>(); }
编译器报错
error[E0597]:
output_filedoes not live long enough
--> src\main.rs:112:18
|
109 | fn read_input_file(input_file: String, path_list: &mut Vec<&str>) {
| - let's call the lifetime of this reference'1
...
112 | *path_list = output_file.split('\n').collect::<Vec<&str>>();
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
| |
| assignment requires thatoutput_fileis borrowed for'1
113 | }
| -output_filedropped here while still borrowed
尝试添加生命周期的修改代码
use std::fs; use std::str::Split; fn read_input_file<'a, 'b>(input_file: String, path_list: &'a mut Vec<&str>) { let output_file = fs::read_to_string(input_file).expect("Should have been able to read the file"); let split: &'b Split<'_, char> = &output_file.split('\n'); *path_list = (*split.clone().collect::<Vec<&str>>()).to_vec(); }
再次报错
error[E0597]:
output_filedoes not live long enough
--> src\main.rs:105:39
|
102 | fn read_input_file<'a, 'b>(input_file: String, path_list: &'a mut Vec<&str>) {
| -- lifetime'bdefined here
...
105 | let split: &'b Split<'_, char> = &output_file.split('\n');
| ------------------- ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
| |
| type annotation requires thatoutput_fileis borrowed for'b
106 | *path_list = (*split.clone().collect::<Vec<&str>>()).to_vec();
107 | }
| -output_filedropped here while still borrowederror[E0716]: temporary value dropped while borrowed
--> src\main.rs:105:39
|
102 | fn read_input_file<'a, 'b>(input_file: String, path_list: &'a mut Vec<&str>) {
| -- lifetime'bdefined here
...
105 | let split: &'b Split<'_, char> = &output_file.split('\n');
| ------------------- ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for'b
106 | *path_list = (*split.clone().collect::<Vec<&str>>()).to_vec();
107 | }
| - temporary value is freed at the end of this statement
问题本质与解决方案
核心问题:output_file是函数内的局部变量,函数执行结束后会被销毁,但你试图传递的Vec<&str>里的所有引用都指向它的内容,这会产生悬垂引用,Rust的所有权系统严格禁止这种不安全的行为。
以下是两种正确的处理方式:
方案1:返回Vec<String>(推荐)
将分割后的字符串转为拥有所有权的String,彻底摆脱对局部变量生命周期的依赖,代码简洁且安全:
use std::fs; // 直接返回Vec<String> fn read_input_file(input_file: String) -> Vec<String> { let output_file = fs::read_to_string(input_file).expect("Failed to read file"); output_file.split('\n').map(|s| s.to_string()).collect() } // 或者用可变引用参数传递结果 fn read_input_file(input_file: String, path_list: &mut Vec<String>) { let output_file = fs::read_to_string(input_file).expect("Failed to read file"); *path_list = output_file.split('\n').map(|s| s.to_string()).collect(); }
方案2:让字符串容器生命周期超出函数范围
如果必须使用Vec<&str>,需要让存储原始字符串的容器(比如String)的生命周期覆盖Vec<&str>的使用周期。可以通过将字符串作为可变参数传入函数实现:
use std::fs; fn read_input_file<'a>(input_file: String, content: &'a mut String) -> Vec<&'a str> { *content = fs::read_to_string(input_file).expect("Failed to read file"); content.split('\n').collect() } // 调用示例 fn main() { let mut file_content = String::new(); let path_list = read_input_file("input.txt".to_string(), &mut file_content); // 注意:file_content必须保持存活,path_list才能有效使用 }
内容的提问来源于stack exchange,提问作者Jerome

