考虑以下程序:
fn func(source: &str, state: & Vec<&str>) {
println!("{}", source);
println!("{}", state[0]);
}
fn step<'a>(source: &'a str, state: &mut Vec<&'a str>) {
state.push(&source[4..10]);
func(source, state);
state.push(&source[4..10]);
}
fn main() {
let source = "abcdefghijklmnopqrstuvwxyz";
{
let mut state = Vec::<&str>::new();
step(source, &mut state);
step(source, &mut state);
step(source, &mut state);
}
}
这将编译并运行而没有错误。我完全理解为什么这里需要使用生命周期说明符'a,否则您可以运行:
fn main() {
let mut state = Vec::<&str>::new();
{
let source = "abcdefghijklmnopqrstuvwxyz";
step(source, &mut state);
step(source, &mut state);
step(source, &mut state);
}
println!("{}", state[0]);
}
这将导致未定义的输出。我的问题是我想将“ func”的两个参数都打包到一个结构中,但是我无法完成这项工作:
struct MyStruct<'a, 'b> {
pub source: &'a str,
pub state: &'b mut Vec<&'b str>,
}
fn func(arg: MyStruct) {
println!("{}", arg.source);
println!("{}", arg.state[0]);
}
fn step<'a>(source: &'a str,
state: &mut Vec<&'a str>) {
state.push(&source[4..10]);
let s = MyStruct{source: source, state: state};
func(s);
state.push(&source[4..10]);
}
fn main() {
let source = "abcdefghijklmnopqrstuvwxyz";
{
let mut state = Vec::<&str>::new();
step(source, &mut state);
step(source, &mut state);
step(source, &mut state);
}
}
上面的代码无法与错误消息一起编译:
107 | state: &mut Vec<&'a str>) {
| ----- consider changing the type of `state` to `&'a mut std::vec::Vec<&'a str>`
108 | state.push(&source[4..10]);
109 | let s = MyStruct{source: source, state: state};
| ^^^^^ lifetime `'a` required
如果我将状态更改为&'a mut Vec <&'a str>,则构建将失败,并显示以下消息:
117 | step(source, &mut state);
| ----- first mutable borrow occurs here
118 | step(source, &mut state);
| ^^^^^ second mutable borrow occurs here
119 | step(source, &mut state);
120 | }
| - first borrow ends here
如果有人能告诉我如何进行这项工作,我将不胜感激。
注意:在此示例程序中,“ source”是具有静态生存期的String。在“实际”程序中,“源”没有静态生存期,但是程序在运行时读取的文件的内容。 “来源”的寿命长于“州”的寿命
答案 0 :(得分:2)
函数参数的生存期情况如下:
fn step<'a>(source: &'a str,
state: &mut Vec<&'a str>)
将没有生命周期明确名称的引用命名为:
fn step<'a, 'x>(source: &'a str,
state: &'x mut Vec<&'a str>)
现在,所有引用都有明确的生存期,我们可以看到结构中的配置与它们在函数参数中如何相互关联不一样。
如果您的结构应遵循相同的关系,我们希望这样做:
struct MyStruct<'a: 'x, 'x> {
pub source: &'a str,
pub state: &'x mut Vec<&'a str>,
}
由于这是一个类型定义,因此我们需要添加在'a: 'x
“'a胜过'x”的函数中隐含的关系
请记住,您还需要确定MyStruct类型的s
变量所拥有的借项的范围-它是可变地借用状态(可变地意味着专有)。因此,您需要在let s = ..
和f(s)
的行周围插入作用域,以便s
的作用域在下一步调用之前结束:
{
let s = MyStruct{source: source, state: state};
func(s);
}