(五)Rust引用和借用
本文最后更新于 2024年6月27日 下午
函数的参数(参数的数据未全部在栈上存储)会转移所有权,Rust中引用传参可以避免所有权转移。引用像是一个指针,它提供了数据存储的地址,通过寻址便能获取实际数据,这和C++语言中的引用传参类似。下面是一个例子:
1 |
|
将&s1
传入calculate_length
,与此同时,在函数定义中,使用&String
代替String
,&
符号代表引用,它允许在函数体中引用某些值但是无需获取所有权。下面图可以帮助理解各个变量关系:
这和C++中的引用非常相似,如果你有C++编程背景,理解Rust中的引用就很容易了。
根据C++的经验思考一个问题:引用在内部可以修改其所指代的实际内容吗?下面看一个例子:
1 |
|
不幸的是,代码无法通过编译,会得到如下错误:error[E0596]: cannot borrow *some_string as mutable, as it is behind a & reference
。
Rust中变量默认是不可变的,引用也是如此,因此无法修改所引用的内容。如果允许修改需要使用可变引用。
可变引用
如何使用可变引用?下面是一个例子:
1 |
|
首先将s
更改为mut
。在调用change
函数时使用&mut
创建一个可变引用,同时更新函数形参为some_string: &mut String
。如此,change
函数中可以对引用内容修改。
可变引用有一个限制:如果一个值有一个可变引用,那么它将不能再有其他引用。下面是一个例子:
1 |
|
Rust是根据引用在代码中最后使用位置,判断其是否违反限制规则,下面是一个合法的例子:
1 |
|
总结:对同一值来说,其非可变引用的使用范围不能与其可变引用的使用范围相交;其可变引用范围内不能包含其它引用。
使用范围:定义引用一行作为起始,最后使用该引用一行作为终止,其中认定为该引用的使用范围。
可以依据上述规则可以尝试不同情况,这里不再赘述。
悬空引用
在其余使用指针的语言中,悬空指针(指针指向内存无效)错误很容易发生。在Rust中,编译器保证所有的引用不会存在悬空引用:编译器保证数据总是后于引用被释放。下面是悬空引用的一个例子,编译器会阻止程序编译:
1 |
|
总结
- 在任意时刻,代码中可以存在一个可变引用或者多个不可变引用。
- 引用一定有效。