Hey Everyone, 大家好,
Today is references and borrowing. Immutable references allow reading data without ownership transfer, while mutable references enable modification, subject to rules ensuring exclusive access and preventing data races.
今天的内容是引用和借用。这是内存安全的基本概念。不可变引用允许阅读数据而不需要所有权转移,而可变引用允许修改,但要遵守确保独占访问和防止数据竞争的规则。
Referencing 引用
Yesterday we saw how passing an argument to a function does the same effect as assigning the value to another variable and effectively resulting in a loss of ownership. Well there’s a workaround to that.
昨天我们看到了如何将参数传递给一个函数与将值分配给另一个变量产生相同的效果,并有效地导致所有权的丧失。有一个解决办法。
If you know anything about C, pointers
are an essential concept of C. Well references are similar.
如果你对C有所了解,那么 pointers
是C的一个基本概念。参考文献是相似的。
Lets take a look at the code and understand it:
让我们看看代码并理解它:
fn main(){
let s1: String = String::from("Hello World");
let length: usize = calculate_length(&s1); // & is used to pass in a reference to a string
println!("The length of `{}` is {}" ,s1,length);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
Rust references are pointers that allow borrowing and accessing data without transferring ownership, promoting memory safety and preventing data races.
Rust引用是指针,允许在不转移所有权的情况下借用和访问数据,促进内存安全并防止数据竞争。
Explanation: 说明:
fn main()
: Entry point of the program.fn main()
:程序的入口点。let s1: String = String::from("Hello World");
: Declares a String variables1
with the value "Hello World".let s1: String = String::from("Hello World");
:声明一个值为“Hello World”的String变量s1
。let length: usize = calculate_length(&s1);
: Calls thecalculate_length
function, passing a reference to the Strings1
.let length: usize = calculate_length(&s1);
:调用calculate_length
函数,传递对Strings1
的引用。fn calculate_length(s: &String) -> usize
: Function that takes a reference to a String (&String
) as a parameter and returns its length as ausize
.fn calculate_length(s: &String) -> usize
:函数接受对String(&String
)的引用作为参数,并将其长度作为usize
返回。s.len()
: Retrieves the length of the String referenced bys
.s.len()
:获取s
引用的String的长度。println!("The length of
{}is {}" ,s1, length);
: Prints the original Strings1
and its length.println!("The length of
{}is {}" ,s1, length);
:打印原始字符串s1
及其长度。
Key concept : 关键概念:
&
is used to pass a reference to the String (&s1
) rather than transferring ownership, preventing the String from being moved or cloned.&
用于传递对String(&s1
)的引用,而不是转移所有权,从而防止String被移动或克隆。- This borrowing allows the
calculate_length
function to operate on the String without taking ownership.
这种借用允许calculate_length
函数在不获取所有权的情况下对String进行操作。 - References are immutable by default
默认情况下,引用是不可变的
Credits to Let's Get Rusty
for this amazing explanation on his YouTube channel.
感谢 Let's Get Rusty
在他的YouTube频道上的这一惊人的解释。
Mutable references 可变引用
What we saw above was an immutable reference, We cannot really change the value but we can read from it. Let’s take a look at mutable references
我们上面看到的是一个不可变的引用,我们不能真正改变值,但我们可以从中读取。让我们看看 mutable references
fn main() {
let mut s1 = String::from("Hello");
// Mutable reference passed to modify_string function
modify_string(&mut s1);
// The original string is now modified
println!("Modified string: {}", s1);
}
fn modify_string(s: &mut String) {
s.push_str(", World!"); // Modifying the string by appending
}
Explanation: 说明:
fn main()
: Entry point of the program.fn main()
:程序的入口点。let mut s1 = String::from("Hello");
: Declares a mutable String variables1
.let mut s1 = String::from("Hello");
:声明一个可变的String变量s1
。modify_string(&mut s1);
: Calls themodify_string
function, passing a mutable reference tos1
.modify_string(&mut s1);
:调用modify_string
函数,传递一个可变引用给s1
。fn modify_string(s: &mut String)
: Function that takes a mutable reference to a String (&mut String
) as a parameter.fn modify_string(s: &mut String)
:将String(&mut String
)的可变引用作为参数的函数。s.push_str(", World!");
: Modifies the String referenced bys
by appending ", World!" to it.s.push_str(", World!");
:通过追加“,World!“对它。println!("Modified string: {}", s1);
: Prints the modified String.println!("Modified string: {}", s1);
:打印修改后的String。
Key concept : 关键概念:
- Mutable references can be passed using
&mut variable_name
.
可变引用可以使用&mut variable_name
传递。
Rules for mutable references
可变引用的规则
- Only one mutable reference or multiple immutable references are allowed for a specific data piece.
对于一个特定的数据块,只允许一个可变引用或多个不可变引用。 - No other references to the same data are allowed while a mutable reference is active.
当可变引用处于活动状态时,不允许对同一数据进行其他引用。 - Mutable references are bound by their scope, preventing dangling references.
可变引用由其作用域绑定,防止悬空引用。 - Only one mutable reference can exist within a specific scope, ensuring coordinated modifications.
在特定范围内只能存在一个可变引用,以确保协调的修改。
In simpler words only one mutable reference to a variable can exist in a particular scope.
简单地说,在一个特定的作用域中,只能存在一个对变量的可变引用。
Although there can be indefinite numbers of immutable references.
尽管不可变引用的数量可以是无限的。
BUT, Immutable and mutable references to the same variable can exist within the same scope.
但是,对同一变量的不可变和可变引用可以存在于同一范围内。
Example: 范例:
fn main(){
let mut string1: String = String::from("Hello World");
let reference1: &String = &string1;
let reference2: &String = &string1;
takes_ownership(reference1);
takes_ownership(reference2);
let _mut_ref: &mut String = &mut string1;
}
fn takes_ownership(_r1: &String){
}
This works just fine because reference1
and reference2
are already out of scope when we created _mut_ref
.
这很好,因为当我们创建 _mut_ref
时, reference1
和 reference2
已经超出了范围。
//This code would result in an error
fn main(){
let mut string1: String = String::from("Hello World");
let reference1: &String = &string1;
let reference2: &String = &string1;
//because of this line
let _mut_ref: &mut String = &mut string1;
takes_ownership(reference1);
takes_ownership(reference2);
}
fn takes_ownership(_r1: &String){
}