关于Rust的所有权/生存期的困惑

时间:2019-04-03 06:40:18

标签: rust

有些功能可以将两件事合而为一:

// It's right. move v1/v2's ownership in when call, move v's ownership back when finish.
fn combine_v(v1: Vec<i32>, v2: Vec<i32>) -> Vec<i32> {
    let v = vec![1,2,3];
    return v;
}

// It's right with lifetime statements. I can return a `&str` type var.
fn combine_s<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    let s = "123";
    return s;
}

// It's not right. 
fn combine<'a>(v1: &'a [i32], v2: &'a [i32]) -> &'a [i32] {
    let a = [1, 2, 3];
    // cannot return reference to local variable `a`
    return &a;
}

// It's not right. 
// Error: the size for values of type `[i32]` cannot be known at compilation time
fn combine_1(v1: [i32], v2: [i32]) -> [i32] {
    let a = [1,2,3];
    return a;
}

所以我有问题:

  1. 为什么您可以返回&str类型但不能返回&[i32]?为什么&str的值在函数完成时不会下降?

  2. (如何)我可以编写一个接受&[i32]并返回新&[i32]的函数吗?

  3. (如何)在编译时无法确定长度时,我可以编写一个接受[i32]并返回新的[i32]的函数吗?

  4. 为什么[i32]必须有一个长度,但&[i32]却没有?

1 个答案:

答案 0 :(得分:1)

以下是您的子问题的答案:

  
    

1)为什么您可以返回&str类型但不能返回&[i32]?为什么&str的值在函数完成后不会下降?

  

由于代码在编译时称为'static生存期。因此,函数完成后不会将其删除。

  
    

2)如何编写一个接受&[i32]并返回新的&[i32]的函数?

  

您的函数签名正确。但是在实现中,您需要使用'static生存期指定声明,或者至少以编译器可以将其称为'static的方式编写声明。 Reference

  
    

3)当无法在编译时确定长度时,如何编写一个接受[i32]并返回新的[i32]的函数?

  

要根据需要使用它们,需要使用Box并按如下所示更改函数签名:Reference

fn combine_1(v1: Box<[i32]>, v2: Box<[i32]>) -> Box<[i32]>
  
    

4)为什么[i32]必须有长度,而&[i32]没有长度?

  

Rust中基本上有2种形式的数组:Reference

  • [T; N]N T个数组,大小已确定。
  • [T]是只有在运行时才知道的大小为T的数组,它不是Sized,只能作为切片(&[T])进行操作。

Playground