Rust学习笔记(10)——引用和解引用的所有权问题

先定义一个struct如下:

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

但我们从最简单的类型开始。我们知道对于简单类型来说,其值是可以copy的,所以下方代码没有任何问题:

fn main() {
    let a = 5;
    let b = &a;
    let mut c = *b; // copy '*b' to c; So c's value is 5.

    c += 10;

    println!("{:?}", c);
    println!("{:?}", b);
    println!("{:?}", a);
}

改变c的值,对a、b没有影响,输出为:

15
5
5

可变引用可以改变原变量的值,下段代码之前运行过:

fn main() {
    let mut a = 5;
    let b = &mut a;

    *b += 10;

    println!("b = {:?}", b);
    println!("a = {:?}", a);
}

输出为:

b = 15
a = 15

那么对于复合型的值呢?不可以对借用进行解引用,因为借用不拥有数据的所有权,所以不能将其借用的数据转移到另一个变量中去。下面带注释行的代码不可编译:

fn main() {
    let a = Point { x: 5, y: 5 };
    let b = &a;
    let c = *b; // Error! cannot move out of `*b` which is behind a shared reference
}

如果将最后一行改为:

let c = (*b).x; // copy '(*b).x' to c;
// or 
let c = b.x; // copy '(*b).x' to c;

则是可行的,因为x为简单类型;如果x未实现copy trait的话,也不行,这个在笔记(6)中学过。同样,在上面这个例子中,将不可变引用全部改为mut,也不行,原因还是因为借用不拥有变量(或数据)的所有权。下面带注释的行同样不可编译:

    let mut a = Point { x: 5, y: 5 };
    let b = &mut a;
    let c = *b; // Error! cannot move out of `*b` which is behind a mutable reference.

如果引用struct中的一个值,能被解引用吗?先看简单值:

fn main() {
    let a = Point { x: 5, y: 5 };
    let b = &a.x;
    let mut c = *b; // copy *b to c;

    c += 20;

    println!("c = {:?}", c);
    println!("b = {:?}", b);
    println!("a = {:?}", a);
}

输出:

c = 25
b = 5
a = Point { x: 5, y: 5 }

可以,但可以看出,简单值还是copy的,对c的改变不影响a。那么值的类型为智能指针类型呢?我们将Point的成员x的类型改为Box<i32>类型试试:

    let a = Point {
        x: Box::new(5),
        y: 5,
    };
    let b = &a.x;
    let c = *b; // Error! move occurs because `*b` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait

答案是不行!*b代表着a的成员x, 其类型是Box类型,未实现Copy trait。因为b为a.x的借用,b不拥有a.x的所有权,所以也不能将*b(也就是a.x)移动到c。

最后:

1、对于复合类型(如struct)的(可变)引用不可解引用;

2、对于复合类型的未实现Copy trait的成员的(可变)引用也不可以解引用。

3、对于1、2两点,可以连续(可变)引用。这个也在笔记(6)中提到过。

之所以啰啰嗦嗦反反复复的写这么多,是因为对于复合数据类型如struct在引用的情况下,在实际应用中所有权会带来很多意想不到的问题。尤其是和Option等结合起来的时候。因为上一篇学到Option的两个方法as_ref() 和 as_mut(),得到的分别是其包含值的引用和可变引用。这个问题本来是在准备写下一篇关于链表节点的操作时临时想到的,又花了点功夫掰扯了一下。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值