将旧Vector内容转移至新Vector:Rust写法合规性及优化疑问
问题解答
是否符合Rust惯用风格?
这种写法能实现需求,但不算最惯用的:
- 要是你只是想把旧Vector的所有权完全转移过去,之后旧Vector要么不用要么重新初始化,直接赋值更简单:
foo.bar = my_vector;。这时候原my_vector会被移动,自动变成空的(之后不能再用,除非重新赋值)。 - 要是你需要保留旧Vector的容器(也就是留着原有的容量,之后还能继续往里加元素),
drain(0..)是可行的,但更直观简洁的写法是用std::mem::take:foo.bar = std::mem::take(&mut my_vector);。这行代码会把my_vector换成一个空Vec(原容量保留),同时把原来的Vec所有权返回给foo.bar,效果和drain(0..).collect()完全一样,但可读性更强。
编译器会怎么处理drain(0..).collect()?
编译器不会把这段代码优化成直接转移原Vector的内存,原因很明确:
Vec::drain(0..)的设计初衷就是保留原Vec的堆内存容量,只清空里面的元素。执行完drain后,原Vec还是握着那块堆内存,只是长度变成0了。collect()创建新Vec的时候,会先根据Drain迭代器知道的元素数量预分配新的堆内存,然后把原Vec里的元素逐个移动(如果元素是可移动类型)或者复制(如果元素实现了Copy)到新Vec里。整个过程不会直接把原Vec的内存块转交给新Vec,因为原Vec还要留着那块内存。
说白了,这种写法会触发一次新的堆分配,还要处理所有元素的移动/复制;如果想避免额外开销,直接转移所有权(foo.bar = my_vector;)或者用std::mem::take是更高效的选择。
内容的提问来源于stack exchange,提问作者fadedbee
相关产品推荐
相关产品推荐

