swap
函数签名:
pub const fn swap<T>(x: &mut T, y: &mut T) {
// SAFETY: the raw pointers have been created from safe mutable references satisfying all the
// constraints on `ptr::swap_nonoverlapping_one`
unsafe {
ptr::swap_nonoverlapping_one(x, y);
}
}
获取两个可变引用,二者必须具有相同的泛型。
fn main() {
let mut a = 1;
let mut b = 2;
std::mem::swap(&mut a, &mut b);
println!("a={} b={}", a, b);
}
测量类型大小
println!("{}", std::mem::size_of::<String>());
- u8,u16,u32…,i8,i16….的大小是稳定的。
- usize,isize平台相关且相等。指针类型如const T , mut T,&T,Box
等大小都跟其相等。 - 可变性和指针大小无关。
- struct 为size加一起加上对齐。
- enum 为tagged unioin需要在最大的字段的基础上加tag,加上对齐。
forget
封装 ManuallyDrop 阻止释放,跟直接用ManuallyDrop封装没啥区别。
replace
提供一个可变引用,一个所有权,返回所有权。而swap是提供两个可变引用。消费掉传入的值,将之替换掉原始值并返回原始值。
take
提供可变引用,返回所有权,可变引用中的内存被替换为default。
对于实现了Default的,我们可以调用mem::take 将其从中取出,替换为default,这也要求我们有可变引用。函数的实现基于replace。
transmute_copy/transmute
- transmute_copy 强转裸指针后读出,不安全。
- transmute 编译器直接将一个类型的值重新解释为另一个类型,官方文档描述为“极其不安全”。非万不得已不要用
ManuallyDrop
被此包装的对象不会随着生命周期自动释放,Box::leak
和 std::mem::forget
都是基于此。
如果不想被ManuallyDrop
包装了,调用 ManuallyDrop::into_inner
又可以将其取出。ManuallyDrop::drop
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
// SAFETY: we are dropping the value pointed to by a mutable reference
// which is guaranteed to be valid for writes.
// It is up to the caller to make sure that `slot` isn't dropped again.
unsafe { ptr::drop_in_place(&mut slot.value) }
}