12

我正在寻找大致这样的东西take,但原子:

impl<T: Clone> for Arc<T> {
    fn take(mut self) -> T {
        Arc::make_mut(&mut self);
        Arc::try_unwrap(self).unwrap()
    }
}

换句话说,我想要Arc::make_mut返回值本身,而不是可变引用。

4

1 回答 1

20

我们可以使用deref*运算符Rc来处理or内部的基础值Arc,然后调用.clone()以返回该值的新拥有的克隆(假设它是可克隆的)。

use std::rc::Rc;

fn main() { 
    let rc = Rc::new("Hello".to_string());
    let mut cloned = (*rc).clone();
    cloned.truncate(4);

    // verify that it's modified
    println!("{:?}", cloned); // "Hell"
    // verify that the original was not
    println!("{:?}", rc); // "Hello"
}

Rc/语义将Arc防止在您的引用存在时创建任何可变引用,因此此操作是线程安全的;克隆数据时无法更改数据。您也不需要对原始基础值的可变引用,因为您没有修改它。

在某些情况下,Rust 允许您省略*deref 运算符:如果您尝试调用不存在于指针上但存在于基础值上的方法,它将隐式取消引用非可变指针类型。但是,在这种情况下我们需要明确,因为/.clone()上确实已经存在一个方法:它用于创建对相同值的新引用。我们不想调用它,所以我们需要显式地取消引用来访问内部类型。RcArc.clone()

我们还可以.clone()通过适当的类型显式调用 Rust 来告诉 Rust 我们想要哪个方法,并且编译器将根据需要隐式应用尽可能多的取消引用。

use std::rc::Rc;

fn main() { 
    let rc3 = Rc::new(Rc::new(Rc::new("Hello".to_string())));
    let mut cloned = String::clone(&rc3);
    cloned.truncate(4);

    // verify that it's modified
    println!("{:?}", cloned); // "Hell"
    // verify that the original was not
    println!("{:?}", rc3); // "Hello"
}
于 2019-04-18T17:05:44.723 回答