在此代码中,sref1
和sref2
是s
的地址,并且地址相同。 ref
和&
有什么区别?
fn main() {
let s = String::from("hello");
let sref1 = &s;
let ref sref2 = s;
println!("{:p}", sref1);
println!("{:p}", sref2);
f1(&s);
f2(s);
}
fn f1(_s: &String) {
println!("{:p}", _s);
}
fn f2(ref _s: String) {
println!("{:p}", _s);
}
_s
中的 f1
和f2
也是字符串的地址,f2
将拥有所有权,但是f2
打印的地址不是字符串的地址。与f1
打印的地址相同。为什么?
答案 0 :(得分:4)
在模式中,&
破坏借项的结构,ref
绑定到按引用而非按值的位置。
换句话说,&
可以帮助您进行借阅,ref
说“借用我匹配的东西到这个地方”
&
和ref
是相反的。
#![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
答案 1 :(得分:3)
&
适用于右值(类型),而ref
适用于左值(变量名称),但是它们都具有相同的作用。
ref
在模式内非常有用,因为您只能访问左值:
#![feature(core_intrinsics)]
fn print_type<T>(_: T) {
println!("{}", unsafe { std::intrinsics::type_name::<T>() })
}
fn main() {
let opt = Some(0);
match opt {
Some(ref i) => print_type(i), // &i32
None => (),
}
}
但是,今天,此关键字并没有真正有用,因为模式匹配更加“巧妙”。它了解到,如果您借用匹配的值,则意味着您要借用内部值:
match &opt {
Some(i) => print_type(i), // &i32
None => (),
}
答案 2 :(得分:3)
在函数参数中,使用
ref
关键字和使用&
符号之间有什么区别?
您已经回答了自己的问题:
[使用
ref
]将获得所有权
将变量的所有权转移到函数,然后获取对已移动变量的引用。也就是说,
fn f2(ref _s: String) {}
等效于
fn f2(s0: String) {
let _s = &s0;
// or
// let ref _s = s0;
}
如果您使用&String
(which you shouldn't),则该函数不拥有该变量的所有权,而仅是对其的引用。
打印的地址[...]不相同
是,因为变量已移动。当变量移动时,其所在的地址可能会更改。这就是为什么它被称为“移动”。
另请参阅: