本来好好的引用,被 rust 玩坏了,搞得自己都不会使用引用了,我们还是从简单的例子入手,来探索使用引用可能遇到额问题。
下面的示例代码编译不通过,在 s1 赋值给变量 s2 的过程中,字符串 neojos 值的所有权由 s1 转移给了 s2,然后 s1 变成了未初始化的状态。
fn main() {let s1: String = "neojos".to_string();let s2 = s1;println!("print s1:{}", s1)
}
假设是 go 语言来实现同样的代码,程序没有任何问题,s1 和 s2 实际指向的同样的字符串,可以正常打印 s1,赋值前后压根不会对 s1 产生影响。而 rust 偏偏要引入所有权的概念,内存中的一个值只能属于一个变量,最终,字符串值属于了 s2 之后,s1 也就相当于被垃圾回收了。
快速解决上述问题的方案,是将赋值的方式修改为引用赋值,就像下面这样,给 s2 赋值的是 s1 的引用,这样 s2 就不能接管 neojos 字符串的所有权,引用赋值过程就属于 借用。下面的方式属于只读借用,对 s2 的任何读操作实际操作的还是 s1 。
fn main() {let s1: String = "neojos".to_string();let s2 = &s1;println!("print s1:{}", s1)
}
如果我们取引用的值,会发生值的移动吗?比如下面的例子,s2 指向了 s1 的可修改引用,s3 试图通过从 s2 取值,那么,s1 变量所拥有的值会发生转移吗?
fn main() {let mut s1: String = "neojos".to_string();let s2 = &mut s1;let s3: String = *s2;println!("print s1:{}", s1);
}
代码编译会发生报错,报错的信息见截图。*s2 确实会发生所有权转移,但 rust 禁止了这样的动作。