Rust 对向量的借用引用的生存期与它所包含的借用指针之间的关系是什么?

Rust 对向量的借用引用的生存期与它所包含的借用指针之间的关系是什么?,rust,rust-obsolete,Rust,Rust Obsolete,编者注:此代码示例来自Rust 1.0之前的版本,在语法上不是有效的Rust 1.0代码。此代码的更新版本会产生不同的错误,但答案仍然包含有价值的信息 我在Rust 0.6中尝试了此代码: fn test<'r>(xs: &'r [&str]) -> &'r str { return xs[0]; } fn测试和'r str{ 返回xs[0]; } 我认为这种类型签名的意思是:“test获取一个借用的指针,其生存期为'r',指向一个指向字符串

编者注:此代码示例来自Rust 1.0之前的版本,在语法上不是有效的Rust 1.0代码。此代码的更新版本会产生不同的错误,但答案仍然包含有价值的信息

我在Rust 0.6中尝试了此代码:

fn test<'r>(xs: &'r [&str]) -> &'r str {
    return xs[0];
}
fn测试和'r str{
返回xs[0];
}
我认为这种类型签名的意思是:“test获取一个借用的指针,其生存期为'r',指向一个指向字符串的借用指针向量,并返回一个指向字符串的借用指针,其生存期也为'r'。但是编译器说:

refs.rs:2:8:2:12错误:不匹配的类型:应为`&'r str`但找到`&str`(生存期不匹配)
参考文献:2返回xs[0];
^~~~
参考文献rs:1:39:3:1注:1:39块上定义的寿命和r。。。
参考文献rs:1 fn试验和r试验{
参考文献:2返回xs[0];
参考文献rs:3}
参考文献rs:1:39:3:1注:……不一定超过1:39在块上定义的匿名生存期#1
参考文献rs:1 fn试验和r试验{
参考文献:2返回xs[0];
参考文献rs:3}
错误:由于上一个错误而中止
这似乎意味着向量中的指针可能不会像(只读)向量本身一样长。这可能吗

我是否需要做一些额外的注释来告诉编译器这是正确的

同样,拥有指针的向量呢

fn test<'r>(xs: &'r [~str]) -> &'r str {
    return xs[0];
}
fn测试和'r str{
返回xs[0];
}
同样,我希望能够借用一个指向向量元素的指针,只要我借用了整个列表

在上下文中,我最初的问题是试图用一个拥有指针的列表扩展一个借用点的列表:

fn extend<'r>(xs: ~[&'r str], ys: &'r [~str]) -> ~[&'r str]

fn extend我想你的意思是:

fn test<'r>(xs: &[&'r str]) ->  &'r str {
        return xs[0];
}
fn测试  &'r str{
返回xs[0];
}
也就是说,取一个借用的数组指针,其中包含指向具有生存期r的字符串的借用指针,并返回其中一个指针,即相同的生存期。向量本身的生存期是无关的


这就是您的第二个示例不起作用的原因,因为您返回的是在函数输入中没有借用的借用指针:数组是借用的,它的内容不是。

我想这就是您的意思:

fn get1<'r, T>(xs: &'r [T]) -> &'r T {
    return &xs[0];
}

fn main() {
    let a = ~[1, 2, 3];
    let b = [1, 2, 3];
    let c = @[1, 2, 3];
    let ax = get1(a);
    let bx = get1(b);
    let cx = get1(c);
    println(fmt!("%d %d %d", *ax, *bx, *cx));
}
fn get1&r T{
返回&xs[0];
}
fn main(){
设a=~[1,2,3];
设b=[1,2,3];
设c=@[1,2,3];
设ax=get1(a);
设bx=get1(b);
设cx=get1(c);
println(fmt!(%d%d%d“,*ax,*bx,*cx));
}

特别是对于字符串,它可能不太好(因为字符串总是通过引用),但是对于值向量,它工作得很好。

第二个版本的
test
,使用拥有的/唯一的字符串确实可以工作,只是必须帮助编译器将
~str
转换为
&r-str

fn test<'r>(xs: &'r [~str]) -> &'r str {
    let tmp: &'r str = xs[0];
    tmp
}
似乎
vec::each(ys)
都能工作,但
ys.each
不能工作,这可能是一个bug(我现在正在调查我打开的)

如果您想就地修改向量,通常的方法是将可变引用传递给向量,即

fn extend<'r>(xs: &mut ~[&'r str], ys: &'r [~str]) {
    for vec::each(ys) |s| {
        let tmp: &'r str = *s;
        xs.push(tmp)
    }
}
从Rust 1.19.0开始(可能从Rust 1.0开始),以下各项:

fn测试和'r str{
xs[0]
}
fn main(){}
委员会:

fn测试和'r str{
&xs[0]
}
fn main(){}
更好的是,生存期推断意味着您不需要在函数上有任何显式的生存期(
fn-test(xs:&[&str])->&str
fn-test(xs:&[String])->&str


我有一种感觉,这个问题归结为编译器如何计算(co-,contra-,in-)生存时间的变化,或者更准确地说,在Rust 1.0之前,它是如何在这种情况下正确计算它的。正如您正确识别的,因为切片包含引用,引用必须比切片寿命长。因此,可以安全地返回与
'r

匹配的较短生存时间的字符串切片。好的,但为什么一个无效的操作?向量怎么能比它里面的引用更长寿?@ThomasLeonard在你的例子中,向量包含指向字符串的指针。如果这些指针不是唯一的指针,那么字符串很容易比向量更长寿。@RamonSnir我怎么能表达相反的意思呢?我想说的是,生成的指针至少在一段时间内有效它与提供的向量一样长(但可能更长)。@ThomasLeonard rodrigo的代码就是这样做的。结果与向量项具有相同的生命周期,必须至少是向量的生命周期。第二个版本的
test
进行了微小的修改,请参见我的答案。不幸的是,更改了签名(返回指向字符串而不是字符串的指针)在我的情况下没有帮助,因为我正在尝试构建一个字符串列表,而不是一个指向字符串的指针列表。我在问题中添加了一个注释,说明了我为什么要这样做。
fn extend<'r>(xs: &mut ~[&'r str], ys: &'r [~str]) {
    for vec::each(ys) |s| {
        let tmp: &'r str = *s;
        xs.push(tmp)
    }
}
rusti> let a = &[~"a", ~"b", ~"c"];
()
rusti> test(a)
"a"
rusti> extend(~["1", "2", "3"], a)
~["1", "2", "3", "a", "b", "c"]
fn test<'r>(xs: &'r [&str]) -> &'r str {
    xs[0]
}

fn main() {}
fn test<'r>(xs: &'r [String]) -> &'r str {
    &xs[0]
}

fn main() {}