在rust里,大多数操作,比如把一个变量赋值给另外一个变量,把变量传递给函数参数,或者从函数返回值都不拷贝值,而是移动,源变量放弃所有权交给目标变量,源变量变成未初始化,目标变量控制它的生命周期。
对于向量,你可以用向量的.clone()方法执行深拷贝,以达到c++的效果,让源变量和目标变量拥有独立的内存数据。
如果你移动一个变量到另外一个已经初始化的变量里,那么目标变量之前的值会被释放。
rust几乎在所有操作里执行移动语义,函数传参和返回函数值,还有构建元组等等。把值给结构体的成员也会移动所有权。
移动听起来似乎是低效的,实际上rust只是浅移动,只移动少量的栈空间,指向的堆内存仍然保持不变,而且通常编译器生成代码的时候足够智能,直接存到目标变量上。
如果一个变量可能发生移动,又没有给它赋新值,那么它就会被认为是未初始化的。
在循环里对一个值执行移动所有权的操作是被禁止的,除非在进入下一个循环之前给它赋了新值。
不是所有的移动都会导致源变量变成未初始化,比如把向量的一个元素赋值给一个变量,这会导致向量的一部分元素是未初始化的,向量需要记住每个元素的状态,是否是初始化的。实际上rust会禁止这种操作,如果你实在需要这么做,应该使用向量自带的方法返回它的元素。
类似向量的集合类型通常提供了方法可以在循环中消费所有的元素。
for in循环会产生移动操作导致向量变成未初始化。for循环的内部机制会获取向量的所有权,并把它分解成元素。由于向量对代码不再可见,在循环中没有方法可以观察向量变成空的过程。
如果你需要一个值离开它的所有者不被编译器跟踪,可以考虑把它的所有者类型换成可以动态跟踪的类型,比如Option。
Option的take方法消费里面的值留None在里面。本身是None怎么办?
