mem::replace() 函数
传入一个同类型的值, 并与目标值进行交换.
该函数的接口如下:
#![allow(unused)] fn main() { pub const fn replace<T>(dest: &mut T, src: T) -> T; }
可以看到, 目标值 dest
是以可变更引用的形式 &mut T
传入的, 这样的话, 类型 T
必须做到内存对齐.
如果无法满足内存对齐的要求, 可以使用 ptr::replace().
接下来看一个基本的示例程序:
use std::mem; fn main() { let mut v = [Box::new(2), Box::new(3), Box::new(4)]; let ret = mem::replace(&mut v[1], Box::new(42)); assert_eq!(*ret, 3); assert_eq!(*v[1], 42); let mut v1 = vec![1, 2, 3]; let mut v2 = vec![4, 5]; // 使用语法糖 (v1, v2) = (v2, v1); v2 = mem::replace(&mut v1, v2); assert_eq!(v2, vec![4, 5]); }
replace() 函数的实现
这个函数的内部实现也较简单, 直接看源代码:
#![allow(unused)] fn main() { use std::ptr; #[inline] pub const fn replace<T>(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! // The compiler optimizes the implementation below to two `memcpy`s // while `swap` would require at least three. See PR#83022 for details. // SAFETY: We read from `dest` but directly write `src` into it afterwards, // such that the old value is not duplicated. Nothing is dropped and // nothing here can panic. unsafe { let result = ptr::read(dest); ptr::write(dest, src); result } } }
整个过程有以下几步:
- 先在栈上创建一个临地对象
result
- 将目标值
dest
的所有字节都拷贝到result
; 发生所有权转移, 此时result
拥有了dest
所指向值的所有权, 但dest
并不会被 drop - 将源值
src
的所有字节都拷贝到dest
; 发生了所有权转移, 此时dest
拥有了src
所指向值的所有权, 但src
并不会被 drop - 最后将
result
返回