References(引用) 、borrowing(借用) 、 &关键字、ref关键字、* 关键字
rust中借用和引用的附带功效都一样,就是都有生命周期。借用使用&关键字,引用使用ref关键字。借用的对象是必须存在的,引用的对象可以虚拟的,后期附上对象。
首先证明的是引用是否可以为空
|
上面代码能编译通过,这说明Rust中的引用和c++ 中的引用不是一个意思,更像c++ 中的指针类型。c++ 通过int *a来声明指针类型。
ref 与 & 的区别
|
两个值都是&i32类型。
所以ref用在变量绑定与&用在表达式上是一样的效果。
看到上一个例子的错误提示,consider borrowing here,那么&在Rust的表达式上可以看成是借用。struct B<'l> {
pub a: &'l u32,
// pub b: ref u32, expected type, found keyword `ref`
}
let ref a = &1;
let b = B{ a: a };
在类型声明上,&表示引用类型。
& 与 * 的关系
那么&用在绑定上是怎么样的?其实&用在绑定上与*用在表达式上是一样的:let r=&1;
let &a=r;
let a=*r;
两个值都是i32类型。
如果上面的解释还没有让你明白他们之间的关系,那么通过代码直接输出具体类型,这能加深理解。#![feature(core_intrinsics)]
fn main() {
let x = &false;
print_type_name_of(x);
let &x = &false;
print_type_name_of(x);
let ref x = &false;
print_type_name_of(x);
}
fn print_type_name_of<T>(_: T) {
println!("{}", unsafe { std::intrinsics::type_name::<T>() })
}
返回结果如下&bool
bool
&&bool
例子:#![feature(core_intrinsics)]
enum Favour<'a> {
Nor(u32),
NorRef(u32),
Ref(&'a u32),
RefRef(&'a u32),
}
fn config(data: &u32) {
println!("log data: {}", data);
}
// fn con(data: ref u32){ //expected type, found keyword `ref`
// println!("log data: {}", data);
// }
fn log(fav: Favour) {
match fav {
Favour::Nor(data) => {
config(&data);
print_type_name_of(data);
},
Favour::NorRef(ref data) => {
config(data);
print_type_name_of(data);
},
Favour::Ref(data) => {
config(data);
print_type_name_of(data);
},
Favour::RefRef(ref data) => {
config(data);
print_type_name_of(data);
}
}
}
fn print_type_name_of<T>(_: T) {
println!("{}", unsafe { std::intrinsics::type_name::<T>() })
}
fn main() {
log(Favour::Nor(1));
log(Favour::Ref(&2));
log(Favour::NorRef(3));
log(Favour::RefRef(&4));
}
结果如下log data: 1
u32
log data: 2
&u32
log data: 3
&u32
log data: 4
&&u32
match的模式匹配上只能使用 ref,在函数声明上只能使用&来表示引用类型
总结
单纯Rust语言上考虑。
我们在不同情况下解释&的意思:
- 在表达式上,表示的是借用。
- 在变量绑定上,表示解地址操作与*类似。
- 在类型声明上,表示引用类型。
- 在模式匹配上,无效关键字
那么ref的通用解释是:
- 在表达式上,无效关键字。
- 在变量绑定上,表示引用类型。
- 在类型声明上,无效关键字。
- 在模式匹配上,表示引用类型。
非要给区分ref和&到底哪个是引用,哪个是借用。我们可以先从词性划分,引用我归类为名词,而借用归类为动词。&A在表达式上 表示借用A,这是一个动作,那结果就是产出一个引用类型。所以let ref B表示声明了一个引用类型,它只能绑定到某次借用动作上。
所以ref 更适合叫引用, &叫借用。