Function std::ptr::read 1.0.0[−][src]
pub const unsafe fn read<T>(src: *const T) -> T
Expand description
从 src
读取值而不移动它。这将使 src
中的内存保持不变。
Safety
如果违反以下任一条件,则行为是未定义的:
-
src
必须是 有效 的才能读取。 -
src
必须正确对齐。如果不是这种情况,请使用read_unaligned
。 -
src
必须指向类型为T
的正确初始化的值。
请注意,即使 T
的大小为 0
,指针也必须非空且正确对齐。
Examples
基本用法:
let x = 12; let y = &x as *const i32; unsafe { assert_eq!(std::ptr::read(y), 12); }Run
手动实现 mem::swap
:
use std::ptr; fn swap<T>(a: &mut T, b: &mut T) { unsafe { // 在 `tmp` 中的 `a` 处创建值的按位副本。 let tmp = ptr::read(a); // 此时退出 (通过显式返回或调用 panics 的函数) 将导致 `tmp` 中的值被丢弃,而 `a` 仍引用相同的值。 // 如果 `T` 不是 `Copy`,则可能触发未定义的行为。 // 在 `a` 中的 `b` 处创建值的按位副本。 // 这是安全的,因为可变引用不能使用别名。 ptr::copy_nonoverlapping(b, a, 1); // 如上所述,退出此处可能会触发未定义的行为,因为 `a` 和 `b` 引用了相同的值。 // 将 `tmp` 移至 `b`。 ptr::write(b, tmp); // `tmp` 已被移动 (`write` 拥有其第二个参数的所有权),因此此处未隐式丢弃任何内容。 } } let mut foo = "foo".to_owned(); let mut bar = "bar".to_owned(); swap(&mut foo, &mut bar); assert_eq!(foo, "bar"); assert_eq!(bar, "foo");Run
归还值的所有权
read
不管 T
是否为 Copy
,都会创建 T
的按位副本。
如果 T
不是 Copy
,则同时使用返回的值和 *src
的值可能会违反内存安全性。
请注意,将分配给 *src
视为一种用途,因为它将尝试丢弃 *src
处的值。
write()
可用于覆盖数据而不会导致数据被丢弃。
use std::ptr; let mut s = String::from("foo"); unsafe { // `s2` 现在指向与 `s` 相同的基础内存。 let mut s2: String = ptr::read(&s); assert_eq!(s2, "foo"); // 分配给 `s2` 会导致其原始值被丢弃。 // 除此之外,由于已释放基础内存,因此不能再使用 `s`。 s2 = String::default(); assert_eq!(s2, ""); // 分配给 `s` 将导致旧值再次被丢弃,从而导致未定义的行为。 // s = String::from("bar"); // 错误 // `ptr::write` 可用于覆盖一个值而不丢弃它。 ptr::write(&mut s, String::from("bar")); } assert_eq!(s, "bar");Run