Skip to content

所有权

介绍

rust 在变量离开作用域时会调用drop()释放内存.

1
2
3
4
5
6
{
    let s = String::from("hello"); // 从此处起,s 是有效的

    // 使用 s
}   // 此作用域已结束,
// drop(s), s 不再有效

注意, 所有权概念只是堆上内存概念, 栈内存不用:

1
2
3
4
5
6
let j;
{
    let i="STR";
    j=i;
}
print!("{}", j);

移动

考虑如下代码:

1
2
3
4
5
6
{
    let s1 = String::from("h/ello");
    let s2 = s1;

    println!("{}, world!", s1);
}

如果 drop(s1) 和 drop(s2), 那么double free, rust 在s2=s1时将s1所有权交给s2, 因此println处会报错.

同样的, 调用函数也会转移所有权:

1
2
3
4
5
6
7
8
fn main(){
    let a=String::from("aaa");
    func(a);
    println!("{}", a); // 报错
}
fn func(a:String){
    // do sth.
}

解法是使用引用, 借用变量所有权:

1
2
3
4
5
6
7
fn calculate_length(s: &String) -> usize {
    s.len()
}

fn change(s: &mute String) {
    s.push_str("a");
}

可变引用在同一时间只能创建一个, 可变引用在同一时间内不可以与非可变引用同时创建:

1
2
3
4
let mut s = String::from("hello");

let r1 = &mut s;
let r2 = &mut s; // 报错
1
2
3
4
let mut s = String::from("hello");

let r1 = s;
let r2 = &mut s; // 报错

解决方法是创建代码块:

1
2
3
4
5
6
7
8
let mut s = String::from("hello");

{
    let r1 = &mut s;

} // r1 在这里离开了作用域,所以我们完全可以创建一个新的引用

let r2 = &mut s;

Slices

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
fn slice_word(s: &str) -> &str{
    &s[..2];
    &s[2..];
    return &s[0..2];
}

fn main() {
    let a=String::from("hello");
    let b=slice_word(&a);
    println!("{}",b);
}