swap

函数签名:

  1. pub const fn swap<T>(x: &mut T, y: &mut T) {
  2. // SAFETY: the raw pointers have been created from safe mutable references satisfying all the
  3. // constraints on `ptr::swap_nonoverlapping_one`
  4. unsafe {
  5. ptr::swap_nonoverlapping_one(x, y);
  6. }
  7. }

获取两个可变引用,二者必须具有相同的泛型。

  1. fn main() {
  2. let mut a = 1;
  3. let mut b = 2;
  4. std::mem::swap(&mut a, &mut b);
  5. println!("a={} b={}", a, b);
  6. }

测量类型大小

  1. 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::leakstd::mem::forget都是基于此。

如果不想被ManuallyDrop包装了,调用 ManuallyDrop::into_inner又可以将其取出。ManuallyDrop::drop

  1. pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
  2. // SAFETY: we are dropping the value pointed to by a mutable reference
  3. // which is guaranteed to be valid for writes.
  4. // It is up to the caller to make sure that `slot` isn't dropped again.
  5. unsafe { ptr::drop_in_place(&mut slot.value) }
  6. }