Rust 中实际移动变量的是什么?
我从未尝试过 C、C++、Go 等语言,所以我决定从 Rust 开始,我已经了解了一些堆栈和堆是什么,但是,移动变量的真正含义是什么? 文档说它不是浅拷贝:
...听起来可能像是在进行浅拷贝。但因为 Rust 也会使第一个变量无效,而不是称其为浅拷贝,所以它被称为移动。在此示例中,我们会说
s1
已移至s2
...
例如:
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1);
文档中提到“无效”时意味着什么。这是否意味着 Rust 使 s1
无效并将 s1
中的值分配给 s2
,所以... s1
> 不存在? o 它有什么价值吗?,这主要是我不明白的,它真的能打动它吗?或者内存中 s1
是否还有任何值?
据我所知,这个检查发生在编译时,所以它让我认为 s1
实际上不存在于内存中,只有 s2
,因为 s1 确实被移动了到s2
。
显然,这种情况发生在大小未知的值(即堆中)上。
我希望你能帮助我理解。 :)
I have never experimented with languages like C, C++, Go, etc., and I decided to start with Rust, I already understand a little what the stack and the Heap are, but, what does it really mean by moving a variable, the documentation says that it is not a shallow copy:
... probably sounds like making a shallow copy. But because Rust also invalidates the first variable, instead of calling it a shallow copy, it’s known as a move. In this example, we would say that
s1
was moved intos2
...
For example:
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1);
What does the documentation mean when it says "invalidates". Does this mean that Rust invalidates s1
and assigns the value that was in s1
to s2
, so... s1
doesn't exist? o Does it have any value?, that's mainly what I don't understand, does it really move it? or is there still any value in s1
in memory?
From what I could understand, this check happens at compile time, so it makes me think that s1
literally doesn't exist in memory and only s2
, since s1 was literally moved to s2
.
Obviously this happens with values that have an unknown size, that is, in the heap.
I hope you can help me understand. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于您提出的几乎每个是/否问题,答案都是“是”和“否”。我们可以在两个不同的上下文中回答这个问题:语言的语义,以及编译器对代码的处理方式。
从语义上讲,将值移至
s2
后,将无法再读取s1
。它可以初始化为新的String
值,然后再次使用。从某种意义上说,“未初始化”和“移出”实际上是相同的状态,因为您必须先为变量分配一些内容,然后才能使用它。 (它们在编译器给出的消息中有点不同,并且结构的子值可以移动,但不能取消初始化。)编译器将对此做什么?嗯,这可能取决于许多因素,包括(但不限于)编译器的版本和所选的优化级别。如果编译器愿意,它可以完全消除移动,因此
s2
实际上只是与s1
相同的内存区域的另一个名称。它还可以在堆栈上为s2
提供自己的内存区域,并将s1
的内容位块传输到其中。关于编译器功能的任何具体答案都必须通过对编译环境、编译器版本和提供给编译器的标志的完整描述来限定。任何拥有的(和未固定的)值都可以移动,无论它是否管理堆上的分配。通常,堆分配本身不会移动。指向堆分配的指针被移动到新位置。 (例如,移动
String
或Vec
不会更改存储实际内容的内存位置。指向该数据的指针只是易手。)The answer is both yes and no to pretty much every yes/no question you asked. There's two different contexts we can answer this in: the semantics of the language, and what the compiler does with the code.
Semantically,
s1
can no longer be read after the value is moved intos2
. It can be initialized to a newString
value and then used again. In a manner of speaking, "uninitialized" and "moved from" are effectively the same state in that you must assign something to the variable before you can use it. (They are a bit different in the messages that the compiler gives, and in that sub-values of a struct can be moved-from, but can't be uninitialized.)What will the compiler do with this? Well, that can depend on many factors, including (but not limited to) the version of the compiler and the optimization level selected. If the compiler wishes to, it can completely elide the move and therefore
s2
in effect becomes just another name for the same region of memory ass1
. It could also gives2
its own region of memory on the stack and blit the contents ofs1
into it. Any specific answer about what the compiler does would have to be qualified with a complete description of the compilation environment, compiler version, and the flags given to the compiler.Any owned (and unpinned) value can be moved, regardless of whether it manages an allocation on the heap. Typically, the heap allocation isn't moved itself. The pointer to the heap allocation is moved to its new location. (For example, moving a
String
or aVec
won't change the memory location where the actual contents are stored. The pointer to that data is just changing hands.)这意味着您作为开发人员无法再访问
s1
。因此,从您的角度来看,您可以认为s1
不存在。不,因为它不存在(从您的角度来看)。
取决于程序和编译器。从概念上讲,确实如此。
即使不谈论移动,一般来说变量可能永远不会在内存中!这取决于优化器做什么。
是的,它发生在编译时。
不,这要看情况。它们两者、其中之一或都不存在于内存、缓存、寄存器中……要知道,您需要检查特定情况。
It means you, as developer, cannot access
s1
anymore. So, from your point of view, you can thinks1
doesn't exist.No, because it doesn't exist (from your point of view).
Depends on the program and the compiler. Conceptually, it does.
Even without talking about moving, variables in general may never be in memory to begin with! It depends on what the optimizer does.
Yes, it happens at compile time.
No, it depends. Both, one or none of them may exist in memory, caches, registers... To know you need to check the particular case.