Rust 在未实现复制特征时重构“克隆”?

Rust 在未实现复制特征时重构“克隆”?,rust,Rust,考虑到我在评论中提到的限制,有没有办法摆脱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

考虑到我在评论中提到的限制,有没有办法摆脱
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);
}
//我们应该对消费者隐藏“数据”
莫德勒乌图书馆{
pub结构Foobar{
数据:Vec//不实现复制的内容
}
impl Foobar{
pub fn new()->Foobar{
福巴{
数据:vec![1,2,3],
}
}
发布fn foo(&self)->字符串{
让我=第三方(self.data.clone());//重构克隆?
格式!(“{}{}”,“foo!”,i)
}
}
//无法更改签名,假设它来自板条箱
第三方发布(数据:Vec)->i32{
数据[0]
}
}
使用leu库::Foobar;
fn main(){
让foobar=foobar::new();
设foo=foobar.foo();
设foo2=foobar.foo();
println!(“{}”,foo);
println!(“{}”,foo2);
}

不,您无法在此处取消对
clone
的调用


这里的问题在于第三方库。由于现在编写了函数
第三方
,因此它确实可以使用
&Vec
;它不需要所有权,因为它只是移出一个
Copy
的值。但是,由于实现不在您的控制范围内,因此没有什么可以阻止维护函数的人员更改它以利用拥有
Vec
的优势。如果允许重写提供的内存,那么无论它在做什么,都可能会更容易或需要更少的内存,函数编写器将为将来这样做敞开大门。如果不是这样的话,那么建议更改第三方函数的签名并同时依赖于
clone

不,您无法摆脱对
clone
的调用

这里的问题在于第三方库。由于现在编写了函数
第三方
,因此它确实可以使用
&Vec
;它不需要所有权,因为它只是移出一个
Copy
的值。但是,由于实现不在您的控制范围内,因此没有什么可以阻止维护函数的人员更改它以利用拥有
Vec
的优势。如果允许重写提供的内存,那么无论它在做什么,都可能会更容易或需要更少的内存,函数编写器将为将来这样做敞开大门。如果不是这样的话,那么建议更改第三方函数的签名并同时依赖于
clone

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

pub fn third_party(data: Vec<i32>) -> i32
pub fn第三方(数据:Vec)->i32
签名是非常明确的:不管这个
第三方
函数做什么,它的API声明它需要自己的
Vec
实例。这就排除了使用任何形式的借用,而且因为
foo()
通过引用接受
self
,所以除了克隆之外,你真的什么都做不了

此外,据说这个
第三方
是在没有任何奇怪的不安全黑客攻击的情况下编写的,因此可以很安全地假设传入它的
Vec
最终被丢弃和释放。因此,在不克隆(通过复制内部指针)的情况下,不安全地创建原始
Vec
的副本是不可能的-如果您这样做,您一定会在免费后得到使用

虽然您的问题没有说明这一点,但您希望保留
数据的原始值这一事实是一种自然的假设。如果这个假设可以放宽,并且您实际上可以给出
数据
实例,例如在内部用空向量替换它,那么您可以做以下几件事:

  • foo(&self)
    切换到
    foo(&mut self)
    ,然后您可以非常轻松地提取
    数据
    ,并将其替换为空向量
  • 使用或存储数据。通过这种方式,您可以继续使用
    foo(&self)
    ,在您从单元格中提取值并将其替换为某个默认值时,需要进行一些运行时检查
  • 但是,这两种方法都会导致丢失原始的
    Vec
    。对于给定的第三方API,这是无法避免的

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

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

    pub fn third_party(data: Vec<i32>) -> i32
    
    pub fn第三方(数据:Vec)->i32
    
    签名是非常明确的:不管这个
    第三方
    函数做什么,它的API声明它需要自己的
    Vec
    实例。这就排除了使用任何形式的借用,而且因为
    foo()
    通过引用接受
    self
    ,所以除了克隆之外,你真的什么都做不了

    此外,据说这个
    第三方
    是在没有任何奇怪的不安全黑客攻击的情况下编写的,因此可以很安全地假设传入它的
    Vec
    最终被丢弃和释放。因此,在不克隆(通过复制内部指针)的情况下,不安全地创建原始
    Vec
    的副本是不可能的-如果您这样做,您一定会在免费后得到使用

    虽然您的问题没有说明这一点,但您希望保留
    数据的原始值这一事实是一种自然的假设。如果这个假设可以放宽,你实际上