首页 文章

Rust中的所有权跟踪:Box <T>(堆)和T(堆栈)之间的差异

提问于
浏览
2

尝试使用编程语言Rust,我发现编译器能够非常准确地跟踪 field of some struct on the stack 的移动(它确切地知道移动了哪个字段) . 但是,当我将结构的一部分放入 Box (即将其放入堆中)时,编译器不再能够确定框中发生的所有事件的字段级移动 . 它将假设整个结构"inside the box"已经移动 . 让我们首先看一下一切都在堆栈上的例子:

struct OuterContainer {
    inner: InnerContainer
}

struct InnerContainer {
    val_a: ValContainer,
    val_b: ValContainer
}

struct ValContainer {
    i: i32
}


fn main() {
    // Note that the whole structure lives on the stack.
    let structure = OuterContainer {
        inner: InnerContainer {
            val_a: ValContainer { i: 42 },
            val_b: ValContainer { i: 100 }
        }
    };

    // Move just one field (val_a) of the inner container.
    let move_me = structure.inner.val_a;

    // We can still borrow the other field (val_b).
    let borrow_me = &structure.inner.val_b;
}

现在 same example but with one minor change :我们将 InnerContainer 放入一个方框( Box<InnerContainer> ) .

struct OuterContainer {
    inner: Box<InnerContainer>
}

struct InnerContainer {
    val_a: ValContainer,
    val_b: ValContainer
}

struct ValContainer {
    i: i32
}


fn main() {
    // Note that the whole structure lives on the stack.
    let structure = OuterContainer {
        inner: Box::new(InnerContainer {
            val_a: ValContainer { i: 42 },
            val_b: ValContainer { i: 100 }
        })
    };

    // Move just one field (val_a) of the inner container.
    // Note that now, the inner container lives on the heap.
    let move_me = structure.inner.val_a;

    // We can no longer borrow the other field (val_b).
    let borrow_me = &structure.inner.val_b; // error: "value used after move"
}

我怀疑它与 nature of the stack vs. the nature of the heap 有关,前者是静态的(至少每个堆栈帧),而后者是动态的 . 也许编译器需要安全地使用它,因为我无法清楚地表达/识别 .

1 回答

  • 10

    在摘要中,堆栈上的 struct 只是一个通用名称下的一堆变量 . 编译器知道这一点,并且可以将结构分解为一组独立的堆栈变量 . 这使它可以独立跟踪每个场的移动 .

    它不能用 Box 或任何其他类型的自定义分配来执行此操作,因为编译器不控制 Box es . Box 只是标准库中的一些代码,而不是语言的固有部分 . Box 无法推断自身的不同部分突然变得无效 . 当摧毁一个 Box 时,它的实现只知道要毁掉一切 .

    换句话说:在堆栈上,编译器完全可以控制,因此可以做一些奇特的事情,例如破坏结构并逐个移动它们 . 一旦自定义分配进入图片,所有投注都会关闭,编译器必须退出并停止尝试变得聪明 .

相关问题