铁锈具有所有权和借款的概念。如果某个函数不借用其参数作为引用,则该函数的参数将被移动,并且一旦超出范围将被释放。
执行此功能:
fn build_user(email: String, username: String) -> User {
User {
email: email,
username: username,
}
}
此函数可以称为:
let email = String::from("foo@example.com");
let username = String::from("username");
let user = build_user(email, username);
由于email
和username
已被移动,因此在调用build_user
之后将无法再使用它们。
可以通过使API使用借来的引用来解决此问题。
请牢记这一点,在设计API时,哪些情况下总是希望不使用借用?
答案 0 :(得分:18)
此列表可能并不详尽,但是很多时候选择不借用参数是有利的。
Copy
类型的效率如果类型较小且实现了Copy
,则通常将其复制而不是传递指针会更有效。引用是指间接的-除了必须执行两个步骤来获取数据之外,指针后面的值不太可能紧凑地存储在内存中,因此复制到CPU缓存的速度较慢,例如,如果要遍历它们。 >
如果您需要保留数据,但是当前所有者需要清理并超出范围,则可以通过将其移至其他地方来转移所有权。例如,您可能在函数中有一个局部变量,但是将其移到Box
中,以便它在函数返回后可以继续使用。
如果一组方法全部消耗self
并返回Self
,则可以方便地将它们链接在一起,而无需中间局部变量。您会经常看到这种用于实现构建器的方法。以下是摘自derive_builder
crate文档的示例:
let ch = ChannelBuilder::default()
.special_info(42u8)
.token(19124)
.build()
.unwrap();
有时,您希望函数使用一个值以保证它不能再次使用,以此作为在类型级别上执行假设的一种方式。例如,在futures
crate中,Future::wait
方法使用self
:
fn wait(self) -> Result<Self::Item, Self::Error>
where
Self: Sized,
此签名专门用于防止您两次调用wait
。该实现无需在运行时进行检查即可查看未来是否已经处于等待状态-编译器将不允许这种情况。
在使用方法链接的构建器时,它还可以防止错误。该设计静态地防止您无序进行操作-创建对象后,您不会意外在构建器上设置字段,因为该构建器被其build
方法消耗了。
某些功能需要拥有自己的数据。可以通过接受引用然后在函数内调用clone
来强制执行 ,但这可能并不总是理想的,因为它向调用者隐藏了潜在的昂贵克隆操作。接受值而不是引用意味着由调用者来克隆值,或者,如果他们不再需要它,则将其移动。