我不明白借贷是如何运作的

Kyr*_*tar -2 compilation rust borrow-checker

我正在尝试编写kd-tree实现,但我一直在收到错误 cannot move out of borrowed content.

这是我的KDTree结构

pub struct KDTree {
    pub bounding_box: Aabb,
    pub axis: Option<Axis>,
    left: Option<Box<KDTree>>,
    right: Option<Box<KDTree>>,
    pub objects: Option<Vec<Box<Geometry>>>,
}
Run Code Online (Sandbox Code Playgroud)

但是,此方法会抛出该错误.

pub fn direct_samples(&self) -> Vec<u32> {
    assert!(self.objects.is_some());
    let mut direct_samples = Vec::new();
    for (i, object) in self.objects
        .expect("Expected tree to have objects")
        .iter()
        .enumerate() {
        if object.material().emittance > 0f32 {
            direct_samples.push(i as u32);
        }
    }
    if self.left.is_some() {
        direct_samples.extend(self.left.unwrap().direct_samples());
    }
    if self.right.is_some() {
        direct_samples.extend(self.right.unwrap().direct_samples());
    }
    direct_samples
}
Run Code Online (Sandbox Code Playgroud)

我明白,如果我改变参数self而不是&self,它应该工作,但是当我调用它时,它会给出错误use of moved value.

pub fn from_objects(objects: Vec<Box<Geometry>>) -> Scene {
    let tree = KDTree::from_objects(objects);

    Scene {
        camera: Camera::new(),
        objects: tree,
        direct_samples: tree.direct_samples(),
    }
}
Run Code Online (Sandbox Code Playgroud)

我是否需要在KDTree上实施复制?难道这不会使用大量的cpu /内存来复制整个东西吗?

Djz*_*zin 5

您的代码需要KDTree所有权的原因是因为您正在呼叫Option::expectOption::unwrap.这些文档可以在这里找到.

impl<T> Option<T> {
    fn unwrap(self) -> T {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当您调用unwrap(或期望)时,编译器会正确地抱怨您按值使用结构的元素.要解决此问题,请使用该Option::as_ref 方法.

impl<T> Option<T> {
    fn as_ref(&self) -> Option<&T> {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这会将对选项的引用转换为可选引用,这不需要所有权.你可以在函数的签名中看到这一点 - 它需要&self而不是self.

pub fn direct_samples(&self) -> Vec<u32> {
    assert!(self.objects.is_some());
    let mut direct_samples = Vec::new();
    for (i, object) in self.objects.as_ref()
        .expect("Expected tree to have objects")
        .iter()
        .enumerate() {
        if object.material().emittance > 0f32 {
            direct_samples.push(i as u32);
        }
    }
    if self.left.is_some() {
        direct_samples.extend(self.left.as_ref().unwrap().direct_samples());
    }
    if self.right.is_some() {
        direct_samples.extend(self.right.as_ref().unwrap().direct_samples());
    }
    direct_samples
}
Run Code Online (Sandbox Code Playgroud)

我是否需要在KDTree上实施复制?难道这不会使用大量的cpu /内存来复制整个东西吗?

你无法实现Copy,KDTree因为它包含堆分配的内存(框) - Copy意味着你的类型只能通过复制其字节来复制,但在这种情况下如果不使单一所有权失效就不会发生.