Box <X> vs X上的移动语义

roy*_*eam 3 rust

我有一个简单的问题Box<X>.我理解它的作用,它X在堆上分配.在C++中,您使用new运算符在堆上分配一些东西,因此它可以比当前作用域更长(因为如果在堆栈上创建某些东西,它会在当前块的末尾消失).

但是阅读Rust的文档,看起来你可以在堆栈上创建一些东西并仍然利用语言的移动语义返回它,而不必求助于堆.然后我不清楚何时使用Box<X>而不是简单地使用X.

我刚刚开始阅读有关Rust的内容,所以如果我遗漏了一些明显的东西,我会道歉.

Luk*_*odt 5

首先: C++ 11(和更新版本)也使用rvalue引用移动语义.所以你的问题也适用于C++.但请记住,C++的移动语义 - 与Rust的不同 - 非常不安全.

第二: "移动语义"这个词以某种方式暗示缺少"副本",这是不正确的.假设你有一个struct100位64位整数.如果你通过移动语义转移这个结构的对象,那么将复制那100个整数(当然,编译器的优化器通常可以删除那些副本,但无论如何......).移动语义的优点在处理堆上处理某种数据的对象(或一般指针)时起到了作用.

例如,看一下Vec(类似于C++ vector):类型本身只包含一个指针和两个指针大小的整数(ptr,lencap).移动向量时仍会复制那些三次64位,但不会触摸向量的主要数据(存在于堆中).


话虽这么说,让我们讨论一个主要问题:" 为什么要使用Box ".实际上有很多用例:

  • Unsized类型:某些类型(例如,也包括闭包的Trait对象)是未分级的,这意味着编译器不知道它们的大小.但是编译器必须知道每个堆栈帧的大小 - 因此那些未经过类型化的类型不能存在于堆栈中.
  • 递归数据结构:考虑BinaryTreeNode结构.它保存了两个名为"左"和"右"的成员...... BinaryTreeNode?那不行.因此,您可以将两个子项打包,以便编译器知道结构的大小.
  • 巨大的结构:想想上面提到的100个整数结构.如果你不想每次都复制它,你可以在堆上分配它(这种情况很少发生).