问题不在于您的引用实际上是可变的,而是它使可变引用保持活动状态。
如果您有参考,请输入&'a ...
or &'a mut ...
,并且您使用它生成另一个引用,无论这是否是重新借用&*some_reference
或现场访问&some_struct_reference.some_field
或方法或其他任何东西,那就是always被认为是一个borrow源自该原始引用,要求原始引用与派生引用一样长久。
请注意,在您的函数声明中,
fn get_shared_references(strings: Vec<&mut String>) -> Vec<&String> {...}
如果我们将其更改为写出省略的生命周期,我们会得到:
fn get_shared_references<'a>(strings: Vec<&'a mut String>) -> Vec<&'a String> {...}
为了使这项工作成功,我们必须为结果编写其他一生,&'b String
而不是“&”字符串。但这个生命周期是怎样的?它是如何受到限制的?它的持续时间不得超过它所指的值确实如此,但比可变引用长。 Rust 的生命周期系统没有办法表达这一点。侥幸逃脱的是:
fn get_shared_references<'m, 'i: 'm>(strings: Vec<&'m mut String>) -> Vec<&'i String> {...}
但即使你可以用这种类型实现一个函数,它对调用者来说也没有用,因为他们不知道关于生命周期的任何事情'i
除了“至少只要'm
".
我们可以想象一个系统,其中可变引用具有两个生命周期 - 让我们假设语法&'m mut 'i T
, where 'm
是引用可变的生命周期,并且'i
是(不长于)值的生命周期。在这种情况下,我们可能有
fn consumes_mut_ref_produces_ref<'m, 'i>(x: &'m mut 'i i32) -> &'i i32 {...}
但必须设计一套全新的生命周期规则才能使这项工作发挥作用,而且甚至可能无法始终如一地做到这一点。这当然不是今天的 Rust 支持的。
在没有关于您想要做什么的更多详细信息的情况下,我的建议是使此代码能够工作owned价值观。拥有的值可以按照您尝试的方式传递 - 因为将它们作为函数参数转移所有权,因此无需担心生命周期,并且更有可能说:“我的函数消耗这个并产生那个”,没有强制关系。
fn append_1_to_all(mut strings: Vec<String>) -> Vec<String> {
for s in strings.iter_mut() {
s.push_str("1")
}
strings
}
fn get_shared_references(strings: &Vec<String>) -> Vec<&String> {
// Or even better, just use strings.iter() instead of this function
strings.iter().collect()
}
#[test]
fn test() {
let strings = vec!["one".to_string(), "two".to_string(), "three".to_string()];
// .clone() here is necessarily only because strings is used in the assert below
let strings_appended = append_1_to_all(strings.clone());
let strings_shared = get_shared_references(&strings_appended);
assert_ne!(strings[0], *strings_shared[0]);
}