借用的向量引用的生命周期与它包含的借用指针之间的关系是什么?

时间:2013-05-20 10:00:58

标签: rust rust-obsolete

  

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

我在Rust 0.6中尝试了这段代码:

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

我认为这种类型的签名意味着:“测试将带有生命周期'的借用指针带到一个借用指向字符串的指针向量,并将一个借用的指针返回给一个字符串,也带有生命周期'r。但编译器说:

refs.rs:2:8: 2:12 error: mismatched types: expected `&'r str` but found `&str` (lifetime mismatch)
refs.rs:2       return xs[0];
                       ^~~~
refs.rs:1:39: 3:1 note: the lifetime &'r  as defined on the block at 1:39...
refs.rs:1 fn test<'r>(xs: &'r [&str]) -> &'r str {
refs.rs:2       return xs[0];
refs.rs:3 }
refs.rs:1:39: 3:1 note: ...does not necessarily outlive the anonymous lifetime #1 defined on the block at 1:39
refs.rs:1 fn test<'r>(xs: &'r [&str]) -> &'r str {
refs.rs:2       return xs[0];
refs.rs:3 }
error: aborting due to previous error

这似乎意味着向量中的指针可能不会像(只读)向量本身一样长。这可能吗?

我需要做一些额外的注释来告诉编译器这没关系吗?

同样,拥有指针的向量怎么样? e.g。

fn test<'r>(xs: &'r [~str]) -> &'r str {
    return xs[0];
}

同样,我希望能够借用指向向量元素的指针,至少只要我借用了整个列表。

对于上下文,我原来的问题是尝试使用自有指针列表扩展借用点列表:

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

计划是:创建一个带有所有借用指针的exended列表,使用它,然后释放扩展列表,然后释放拥有指针的原始列表,包括包含的字符串。

3 个答案:

答案 0 :(得分:4)

test的第二个版本,拥有/唯一字符串确实有效,只需要协助编译器将~str转换为&'r str

fn test<'r>(xs: &'r [~str]) -> &'r str {
    let tmp: &'r str = xs[0];
    tmp
}

这个工作的原因是xs向量拥有它包含的~str,因此编译器知道它们的生命周期至少是向量的生命周期(因为它也在关注可变性)像这样借用的存在,所以字符串永远不能从矢量中删除)。唯一的问题是说服编译器将xs[0]强制转换为切片,这最容易由临时执行。


extend可能类似于:

fn extend<'r>(xs: ~[&'r str], ys: &'r [~str]) -> ~[&'r str] {
    let mut xs = xs;
    for vec::each(ys) |s| {
        let tmp: &'r str = *s;
        xs.push(tmp)
    }
    xs
}

似乎vec::each(ys)有效,但ys.each没有,这可能是一个错误(我正在调查它我打开了#6655

如果要在原位修改矢量,通常的方法是将可变引用传递给矢量,即

fn extend<'r>(xs: &mut ~[&'r str], ys: &'r [~str]) {
    for vec::each(ys) |s| {
        let tmp: &'r str = *s;
        xs.push(tmp)
    }
}

被称为extend(&mut vec, additions)


举例说明:

rusti> let a = &[~"a", ~"b", ~"c"];
()
rusti> test(a)
"a"
rusti> extend(~["1", "2", "3"], a)
~["1", "2", "3", "a", "b", "c"]

答案 1 :(得分:3)

我认为你的意思是:

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

也就是说,你把一个借来的数组指针包含带有生命周期r的字符串的借来的指针,并返回其中一个指针,相同的生命周期。载体本身的寿命是无关紧要的。

这就是你的第二个例子无法工作的原因,因为你正在返回一个借用的指针,这个指针没有在函数的输入中借用:数组被借用,其内容不是。

答案 2 :(得分:0)

我认为这就是你的意思:

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));
}

特别是对于字符串,它可能不太好(因为字符串总是按引用),但是使用值向量 - 它可以正常工作。