引用是作为参数传递给函数的地址。借用就像我们借一些东西,如果已经完成借用,需要还给原所有者。 引用和借用是相互的,即当引用被释放时,借用也结束。
为什么要借用?
使用借用概念的原因如下:
- 借用允许对单个资源进行多次引用,但仍然遵守“单一所有者”。
- 引用就像C中的指针一样。
- 引用是一个对象。 引用有两种类型,即可变引用和不可变引用。 在复制不可变引用时移动可变引用。
下面通过一个例子来理解这一点。
fn main()
{
let str=String::from("Yiibai");
let len=calculate_length(&str);
println!("length of the string {}",len);
}
fn calculate_length(s:&String)->usize
{
s.len()
}
执行上面示例代码,得到以下结果 -
length of the string 6
在上面的示例中,calculate_length()
函数对字符串str
的引用作为参数而不取其所有权。
let str=String::from("Yiibai");
let len=calculate_length(&str);
在上面的场景中,&str
是对变量str
的引用,但它并不拥有它。 因此,即使引用超出范围,也不会删除引用指向的值。
fn calculate_length(s:&String)->usize
s.len()
在上面的例子中,变量s
有效,直到控制没有返回main()
函数。 当变量作为函数的引用而不是实际值传递时,不需要返回值到返回所有权。
下面尝试修改借用的值。
fn main()
{
let x=1;
value_changed(&x)
}
fn value_changed(y:&i32)
{
*y=9;
}
以下是上述程序的输出:
在上面的示例中,它会引发错误,因为&x
是不可变引用。 因此,无法改变y
的值。
可变引用
可以通过使用可变引用来修复上述错误。可变引用是那些可以改变的引用。下面通过一个例子来理解这一点。
fn main()
{
let mut x=1;
value_changed(&mut x);
println!("After modifying, the value of x is {}",x);
}
fn value_changed(y:&mut i32)
{
*y=9;
}
执行上面示例代码,得到以下结果 -
After modifying, the value of x is 9
在上面的例子中,创建了一个可变引用,即&mut x
,引用由变量y
指向,它是&i32
类型。 现在,可以更改y
变量引用的值。分配9
个值,即* y = 9
。 因此,x
的值也变为9
,作为两个变量引用的相同内存位置。
可变引用的限制
只能对特定范围内的一段数据进行一次可变引用。
例如:
let mut str=String::from("Yiibai");
let a= &mut str;
let b= &mut str;
在上面的场景中,编译器抛出一个错误,因为它包含两个在Rust语言中不可能的可变引用。如果程序中存在不可变引用,那么程序中就不能有可变引用。
例如:
let mut str=String::from("Yiibai");
let a= &str;
let b=&str;
let c=&mut str;
在上面的场景中,编译器抛出一个错误,因为当有一个不可变引用时,不能有一个可变引用。