Pas*_*cht 9 api-design reference move-semantics rust borrowing
Rust拥有所有权和借贷的概念.如果函数没有将其参数作为引用借用,则该函数的参数将被移动,并且一旦超出范围将被释放.
采取这个功能:
fn build_user(email: String, username: String) -> User {
User {
email: email,
username: username,
}
}
Run Code Online (Sandbox Code Playgroud)
此功能可以称为:
let email = String::from("foo@example.com");
let username = String::from("username");
let user = build_user(email, username);
Run Code Online (Sandbox Code Playgroud)
由于email
与username
已被移动,他们不能再被使用之后build_user
被调用.
这可以通过使API使用借来的引用来修复.
考虑到这一点,在设计API时,哪些场景总是倾向于不使用借用?
Pet*_*all 19
这个清单可能并不详尽,但有很多时候选择不借用论证是有利的.
Copy
类型如果一个类型很小并且实现Copy
,那么复制它通常更有效,而不是传递指针.引用意味着间接 - 除了必须执行两个步骤来获取数据之外,指针后面的值不太可能紧密地存储在内存中,因此复制到CPU缓存中的速度较慢,例如,如果您在迭代它们.
当您需要数据时,但当前所有者需要清理并超出范围时,您可以通过将其移动到其他位置来转移所有权.例如,您可能在函数中有一个局部变量,但将其移动到一个变量,Box
以便它可以在函数返回后继续存在.
如果一组方法全部消耗self
并返回Self
,则可以方便地将它们链接在一起,而不需要中间局部变量.您经常会看到这种方法用于实现构建器.以下是从derive_builder
包装箱文档中提取的示例:
let ch = ChannelBuilder::default()
.special_info(42u8)
.token(19124)
.build()
.unwrap();
Run Code Online (Sandbox Code Playgroud)
有时,您希望函数使用一个值来保证它不能再次使用,作为在类型级别强制执行假设的一种方法.例如,在futures
包中,该Future::wait
方法消耗self
:
fn wait(self) -> Result<Self::Item, Self::Error>
where
Self: Sized,
Run Code Online (Sandbox Code Playgroud)
此签名专门用于防止您拨打wait
两次电话.实现不必在运行时检查未来是否已经处于等待状态 - 编译器不会允许这种情况.
使用方法链式构建器时,它还可以防止错误.该设计静态地阻止您执行任何操作 - 在创建对象后,您不能在构建器上意外设置字段,因为构建器由其build
方法使用.
有些功能需要拥有自己的数据.这可以通过接受引用然后clone
在函数内调用来强制执行,但这可能并不总是理想的,因为它隐藏了来自调用者的潜在昂贵的克隆操作.接受值而不是引用意味着由调用者来克隆值,或者如果他们不再需要它,则移动它.
归档时间: |
|
查看次数: |
411 次 |
最近记录: |