gpt4 book ai didi

rust - 未实现复制特征时重构 `clone`?

转载 作者:行者123 更新时间:2023-12-03 11:33:16 25 4
gpt4 key购买 nike

考虑到我在注释中指出的限制,是否有办法摆脱clone()?我真的很想知道在这种情况下是否可以使用借用,因为在这种情况下无法修改第三方功能签名。

// We should keep the "data" hidden from the consumer
mod le_library {
pub struct Foobar {
data: Vec<i32> // Something that doesn't implement Copy
}

impl Foobar {
pub fn new() -> Foobar {
Foobar {
data: vec![1, 2, 3],
}
}

pub fn foo(&self) -> String {
let i = third_party(self.data.clone()); // Refactor out clone?

format!("{}{}", "foo!", i)
}
}

// Can't change the signature, suppose this comes from a crate
pub fn third_party(data:Vec<i32>) -> i32 {
data[0]
}
}

use le_library::Foobar;

fn main() {
let foobar = Foobar::new();
let foo = foobar.foo();
let foo2 = foobar.foo();
println!("{}", foo);
println!("{}", foo2);
}

playground

最佳答案

只要您的foo()方法接受&self,就不可能,因为

pub fn third_party(data: Vec<i32>) -> i32

签名是非常明确的:无论此 third_party函数做什么,API均按值要求它需要自己的 Vec实例。这排除了使用任何形式的借用的可能性,并且因为 foo()通过引用接受 self,所以除了克隆外,您实际上无法做任何事情。

同样,据说此 third_party的编写没有任何奇怪的不安全的技巧,因此可以很安全地假定传递给它的 Vec最终会被丢弃并释放。因此,不安全地创建原始 Vec的副本而不克隆(通过复制内部指针)是不成问题的-如果您这样做,肯定会获得免费使用。

虽然您的问题没有说明,但是您想要保留 data的原始值的事实是一种自然的假设。如果可以放宽这个假设,而您实际上可以将 data实例提供给其他人,例如在内部用一个空向量替换它,那么您可以做几件事:
  • foo(&self)切换为foo(&mut self),然后可以很容易地提取data并将其替换为空向量。
  • 使用 Cell RefCell 存储数据。这样,当您从单元格中提取值并将其替换为某些默认值时,您可以继续使用foo(&self),但要花一些运行时检查的代价。

  • 但是,这两种方法都会导致您丢失原始的 Vec。有了给定的第三方API,就无法解决此问题。

    如果您仍然可以以某种方式影响此外部API,那么最好的解决方案是将其更改为接受 &[i32],可以通过借用从 Vec<i32>轻松获得它。

    关于rust - 未实现复制特征时重构 `clone`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60048103/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com