RUST 引用

let x = 5;指针

let y = &5;内存

let z= &x;编译器

x 是 i32 整型,y,z 是引用类型,用 & 是取引用符it

新加变量 x, 并绑定 5 数据,编译

新增长变量 y,并绑定 5 数据的引用地址变量

新增变量 z, 并绑定 x 的引用地址原理

上面每一个变量在内存中都是不一样的存储引用

第一行,在栈中添加变量,并且变量的值是 5,都在栈中程序

第二行,在栈中增长一个数据 5,再再栈中建立一个变量 y,并把 5 所在的内存地址,给 y;im

第三行 在栈中增长一个变量,把 x 所在的内存地址赋值给 z

每行都是在内存新开辟一块空间,存变量,并且变量的值都是不一样的,y 和 z 的内存地址并不相同

let x = 5;

let h = &x;

let k = &x;

上面 h,k 拥有相同的值,x 的内存地址肯定,h,k 都是取 x 的内存地址,全部 h 和 k 是同等的,根据以前的说明,那若是

let g = &5; 是否是就说明 h==k 是 true, h==g 是 false,k==g 也是 false

其实否则,虽然 g=&5; g 的值和 h,k 都不相同,可是在调用 == 的时候,会产生自动解码的操做,会直接比较指针的值因此,h==g 和 k==g 都是 true

有点须要特别说明,指针的指针这种状况,看下面例子, 先不提有没有必要,编译器是支持的

let x = 5;

let y = &&x;

let z = &&x;

y 和 z 的内存地址是不相同的,具体的原理不是很明白,就根据个人理解(我让我信服的理由)&x 取 x 的引用保存到一块空间,&&x 而后再取这个空间的地址,由于咱们并无把 &x; 存这块空间绑定到一个变量上,因此每次取 &x, 都会产生一个新的空间,因此每次取这个地址都是一个新的内存地址。

 

最后说下解引用,就是用 * 号来解引用,使用引用指向的数据,若是没有解引用,那就是

let x = 5;

let y = &5;

let z = x+*y;

上面代码没有错,正常编译执行,y 的类型是个 引用类型,* 号把 y 解引用就是 5,相加正常,

若是 z 换成 let z = x+y; 呢,也是正常执行和编译的,这是由于编译器自动把 y 解引用了,

impl<'a,'b> Add<&'a i32> for &'b i32

fn add(self, other: &'a i32) -> >::Output

相似于如何使用 Deref trait 重载不可变引用的 * 运算符,Rust 提供了 DerefMut trait 用于重载可变引用的 * 运算符。

Rust 在发现类型和 trait 实现知足三种状况时会进行解引用强制多态:

当 T: Deref 时从 &T 到 &U。

当 T: DerefMut 时从 &mut T 到 &mut U。

当 T: Deref 时从 &mut T 到 &U。

头两个状况除了可变性以外是相同的:第一种状况代表若是有一个 &T,而 T 实现了返回 U 类型的 Deref,则能够直接获得 &U。第二种状况代表对于可变引用也有着相同的行为。

最后一个状况有些微妙:Rust 也会将可变引用强转为不可变引用。可是反之是 不可能 的:不可变引用永远也不能强转为可变引用。由于根据借用规则,若是有一个可变引用,其必须是这些数据的惟一引用(不然程序将没法编译)。将一个可变引用转换为不可变引用永远也不会打破借用规则。将不可变引用转换为可变引用则须要数据只能有一个不可变引用,而借用规则没法保证这一点。所以,Rust 没法假设将不可变引用转换为可变引用是可能的

做者:zqliang 连接:https://hacpai.com/article/1540173433079 来源:黑客派 协议:CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/

相关文章
相关标签/搜索