不借用的API在哪些场景下是首选?

Posted

技术标签:

【中文标题】不借用的API在哪些场景下是首选?【英文标题】:In what scenarios are APIs that don't borrow preferred? 【发布时间】:2019-05-17 03:39:34 【问题描述】:

Rust 具有所有权和借贷的概念。如果函数不借用其参数作为引用,则该函数的参数将被移动,并且一旦超出范围就会被释放。

取这个函数:

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);

由于emailusername 已被移动,因此在调用build_user 后它们将无法再使用。

这可以通过让 API 使用借用的引用来解决。

考虑到这一点,在设计 API 时,哪些场景总是倾向于不使用借用?

【问题讨论】:

函数build_user() 将参数移动到结构User 中。如果您想使用借用编写相同的函数,则不能将它们移动到结构中,因为您不拥有它们,因此您必须克隆它们(或更改 User 的定义以存储借用) . 我认为这个问题对于 *** QA 格式来说有点太宽泛太模糊了。 感谢 cmets!不幸的是,他们似乎没有解决我的问题。如果它太宽泛,我很乐意让它更具体。有什么建议?我只是想知道为什么或何时想要创建一个不借用的 API。必须有案例。 我的评论并不是作为一个答案,而是要指出你声称你也可以使用借用的说法是不正确的。作为推论,这个函数是一个通常按值获取参数的函数的示例,因为它需要所有权。如果您想要更多示例,只需查看标准库即可。按值接受参数的函数通常不能写成借用。 之所以我认为这个过于笼统,是因为回答这个问题基本上是为了解释 Rust 的所有权制度。对此已有很好的介绍,例如 Rust 书中关于所有权的章节。 【参考方案1】:

此列表可能并不详尽,但很多时候选择不借用论点是有利的。

1。小型Copy 类型的效率

如果一个类型很小并且实现了Copy,那么复制它通常比传递指针更有效。引用意味着间接 - 除了必须执行两个步骤来获取数据之外,指针后面的值不太可能紧凑地存储在内存中,因此复制到 CPU 缓存中的速度较慢,例如,如果您正在迭代它们。

2。转让所有权

当您需要保留数据,但当前所有者需要清理并超出范围时,您可以通过将其移动到其他地方来转移所有权。例如,您可能在函数中有一个局部变量,但将其移动到 Box 中,以便在函数返回后它可以继续存在。

3。方法链

如果一组方法都消耗self并返回Self,您可以方便地将它们链接在一起,而无需中间的局部变量。您经常会看到这种方法用于实现构建器。以下是取自derive_builder crate 文档的示例:

let ch = ChannelBuilder::default()
    .special_info(42u8)
    .token(19124)
    .build()
    .unwrap();

4。静态强制执行不变量

有时,您希望函数使用一个值以保证它不能再次使用,作为在类型级别强制执行假设的一种方式。比如futures crate中,Future::wait方法消耗self

fn wait(self) -> Result<Self::Item, Self::Error> 
where
    Self: Sized,

此签名专门用于防止您调用wait 两次。实现不必在运行时检查未来是否已经处于等待状态 - 编译器不会允许这种情况。

它还可以在使用方法链构建器时防止错误。该设计静态地防止您乱序操作 - 您不会在创建对象后意外地在构建器上设置字段,因为构建器被其 build 方法使用。

5。使克隆对调用者明确

有些函数需要拥有自己的数据。这可以通过接受一个引用然后在函数中调用clone 来强制执行,但这可能并不总是理想的,因为它对调用者隐藏了潜在的昂贵的克隆操作。接受该值而不是引用意味着由调用者来克隆该值,或者,如果他们不再需要它,则改为移动它。

【讨论】:

以上是关于不借用的API在哪些场景下是首选?的主要内容,如果未能解决你的问题,请参考以下文章

高并发场景下锁

如何使用 philips hue API 创建“场景”

OCR API接口具体有哪些?

阿里一面,说说你了解zookeeper的应用场景有哪些?

公司移动办公需求主要应用于哪些场景

Unity查找脚本被哪些Perfab或场景引用