Catalyst

Rust 笔记(五)借用与生命周期

感觉过段时间再看就不一样了,经常更新预定。

借用

借用,理解为变量的所有权的转移,与之对应的还有消耗(consume)。

fn main() {
    let a = "测试".to_string();
    let b = a;
    println!("b={}", b);
    println!("a={}", a);
}

由于a的变量所有权发生转移,所以最后的打印语句无法执行。

error[E0382]: borrow of moved value: `a`
 --> lifetime.rs:5:22
  |
2 |     let a = "测试".to_string();
  |         - move occurs because `a` has type `String`, which does not implement the `Copy` trait
3 |     let b = a;
  |             - value moved here
4 |     println!("b={}", b);
5 |     println!("a={}", a);
  |                      ^ value borrowed here after move

如果使用引用则没有问题:

fn main() {
    let a = "测试".to_string();
    let b = &a;
    println!("b={}", b);
    println!("a={}", a);
}
/*
b=测试
a=测试
*/

同时只能持有多个不变引用或一个可变引用

//这样不行
fn main() {
    let mut a = "测试".to_string();
    let b = &a;
    let c = &a;

    let d = &mut a;
    d.push_str("_D");

    println!("b={}, c={}", b, c);
    println!("d={}", d);
    println!("a={}", a);
}
//这样可以
fn main() {
    let mut a = "测试".to_string();
    let b = &a;
    let c = &a;
    println!("b={}, c={}", b, c);

    let d = &mut a;
    d.push_str("_D");

    println!("d={}", d);
    println!("a={}", a);
}
/*
b=测试,c=测试
d=测试_D
a=测试_D
*/
//这样也可以
fn main() {
    let mut a = "测试".to_string();

    let d = &mut a;
    d.push_str("_D");
    println!("d={}", d);

    let b = &a;
    let c = &a;
    println!("b={}, c={}", b, c);

    println!("a={}", a);
}
/*
d=测试_D
b=测试_D, c=测试_D
a=测试_D
*/

另:用被大括号括住的块结算生命周期。

//这样不行
fn main() {
    let a;
    {
        let b = "B".to_string();
        a = &b;
    }
    println!("a={}", a);
}

括号完毕后 b 的生命周期视为结束,被释放。a 的借用找不到原变量,失效。

生命周期

生命周期用于保证不空引用/借用。

生命周期声明不影响实际的生命周期,只是描述了不同参数间的生命周期关系。

生命周期声明

fn func<'a>(a:&'a i32, b:&`a i32){
  //<略>
}

这样的声明说明 a 和 b 的生命周期都是'a'a在这里没有实际意义,仅表示一个提示编译器的签名,提示有相同签名的变量有相同的生命周期。

特殊的声明是'static,表示一直存在,所有的str常量类型都有静态生命周期。

参考资料