rust - 消费 self 并返回它对性能有何影响?

标签 rust ownership

我一直在阅读类似 Why does a function that accepts a Box<MyType> complain of a value being moved when a function that accepts self works? 的问题, Preferable pattern for getting around the "moving out of borrowed self" checker , 和 How to capture self consuming variable in a struct? ,现在我很好奇消费 self 但可能将其返回给调用者的性能特征。

举一个更简单的例子,假设我想创建一个保证非空的集合类型。为此,“删除”操作需要使用集合并有选择地返回自身。

struct NonEmptyCollection { ... }

impl NonEmptyCollection {
    fn pop(mut self) -> Option<Self> {
        if self.len() == 1 {
            None
        } else {
            // really remove the element here
            Some(self)
        }
    }
}

(我想它也应该返回它从列表中删除的值,但这只是一个例子。)现在假设我调用这个函数:

let mut c = NonEmptyCollection::new(...);
if let Some(new_c) = c.pop() {
    c = new_c
} else {
    // never use c again
}

对象的内存实际上发生了什么?如果我有这样的代码怎么办:

let mut opt: Option<NonEmptyCollection> = Some(NonEmptyCollection::new(...));
opt = opt.take().pop();

函数的签名并不能保证返回的对象实际上是同一个对象,那么有什么优化可能呢? C++ 返回值优化之类的东西是否适用,允许返回的对象在它之前所在的同一内存中“构造”?如果我可以在上面的接口(interface)和调用者必须处理生命周期的接口(interface)之间进行选择:

enum PopResult {
    StillValid,
    Dead
};

impl NonEmptyCollection {
    fn pop(&mut self) -> PopResult {
        // really remove the element
        if self.len() == 0 { PopResult::Dead } else { PopResult::StillValid }
    }
}

出于性能原因,是否有理由选择这种较脏的接口(interface)?在answer to the second example I linked , trentcl 建议将 Option 存储在数据结构中,以允许调用者就地进行更改,而不是每次执行 remove 后跟 insert时间。这个肮脏的接口(interface)会是一个更快的选择吗?

最佳答案

YMMV

根据优化器的突发奇想,您最终可能会得到:

  • 接近空操作,
  • 一些注册 Action ,
  • 一些位拷贝。

这将取决于是否:

  • 调用是否内联,
  • 调用者重新分配给原始变量或创建一个新变量(以及 LLVM 如何处理重用死空间),
  • size_of::<Self>() .

你得到的唯一保证是不会发生深拷贝,因为没有 .clone()打电话。

对于其他任何事情,您需要检查 LLVM IR 或程序集。

关于rust - 消费 self 并返回它对性能有何影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48226014/

相关文章:

c++ - 将 unique_ptr 用于所有权,否则使用原始指针?

rust - '@' 符号在 Rust 中有什么作用?

c++ - 单一与共享所有权的含义

c - 我是否将数组所有权从我的库函数传回给调用者?

error-handling - 如何将 std::io::Error 与 Windows 错误代码进行匹配?

sql - EXECUTE AS OWNER 的存储过程是否可以有效替代从第三个模式表中选择的 View ?

c++ - 可以在运行时更改所有权的智能指针 (C++)

stream - 我如何每 N 秒从无界队列中提取消息并将它们生成到 Tokio 处理程序?

rust - 我如何在 Rust 中定义一个泛型结构,而其中一个字段不是泛型类型?

rust - 如何让 Cargo 将包的名称/版本保存到 "[dependencies]"文件的 "Cargo.toml"部分?