作为一名学习 Rust 的 C++ 程序员新手,我对所有权以及借用检查器的工作原理并不完全满意,因此在尝试它时,我想到了一个我想询问的类比。我是否可以将 rusts 的所有权转移视为编译器在借用任何堆分配值的任何函数调用之后立即插入一个 free,例如:
analogy(Type* val) {
...
}
function() {
Type* arg = new Type()
analogy(arg)
// Could I think of the borrow checker on assumption
// as a preprocessor that inserts the following
delete arg
// After doing so, a static analyzer is run by the compiler
// which can trivially detect an error such as this
print(arg)
}
以下解释是一个简化的模型,但它应该可以帮助您入门。
new
和 delete
是相反的,就像 {
和 }
一样。最好用很多大括号来考虑它,其中左大括号类似于引入一个新变量,并且可能是 new
。右大括号代表变量生命周期的结束,也可能代表 delete
:
{
Foo x = new ...;
{
Foo y = &x; // y's introduction lacks 'new'
bar(y); // function calls do not imply 'new'
// so no 'delete' here
}
// y is inaccessible here without extending the closing brace
bar(x);
print(x);
delete x;
}
// x is inaccessible here
实际上,标准库中已经有一个类比:您可以使用运行时借用检查与RefCell
(单线程)或
RwLock
(多线程)来代替编译时借用检查).因此,我们可以使用 来转换示例,在操场上尝试一下:
use std::cell::RefCell;
pub fn original() {
let mut x = String::from("Hello, world!");
let y = &x;
// x.push('!'); // Borrow-checking error.
println!("{y:?}");
x.push('!');
println!("{x:?}");
}
pub fn converted() {
let x = RefCell::new(String::from("Hello, world!"));
let y = x.borrow();
// x.borrow_mut().push('!'); // Panic.
println!("{y:?}");
x.borrow_mut().push('!');
println!("{x:?}");
}
因此,最好将借用视为读写锁定,而不是临时“删除”:
&T
锁定读取,并且允许多个读取者,但不允许写入者。
&mut T
锁定写入,不允许其他读取器或写入器。