Function core::ptr::copy_nonoverlapping

1.0.0 (const: 1.63.0) · source ·
pub const unsafe fn copy_nonoverlapping<T>(
    src: *const T,
    dst: *mut T,
    count: usize
)
Expand description

count * size_of::<T>() 字节从 src 复制到 dst。源和目标必须不重叠。

对于可能重叠的内存区域,请改用 copy

copy_nonoverlapping 在语义上等同于 C 的 memcpy,但交换了参数顺序。

副本是 “untyped”,因为数据可能未初始化或违反 T 的要求。初始化状态被完全保留。

Safety

如果违反以下任一条件,则行为是未定义的:

  • 对于 count * size_of::<T>() 字节的读取,src 必须是 valid

  • 对于 count * size_of::<T>() 字节的写入,dst 必须是 valid

  • srcdst 必须正确对齐。

  • src 开始的内存区域,大小为 count * size_of::<T> () 字节不得与以 dst 开始且大小相同的内存区域重叠。

read 一样,无论 T 是否为 Copycopy_nonoverlapping 都会创建 T 的按位副本。 如果 T 不是 Copy,则使用两个以 *src 开头的区域和以 *dst 开头的区域中的值可以 违反内存安全

请注意,即使有效复制的大小 (count * size_of::<T>()) 是 0,指针也必须非空的并且正确对齐。

Examples

手动实现 Vec::append

use std::ptr;

/// 将 `src` 的所有元素移到 `dst`,将 `src` 留空。
fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
    let src_len = src.len();
    let dst_len = dst.len();

    // 确保 `dst` 具有足够的容量来容纳所有 `src`。
    dst.reserve(src_len);

    unsafe {
        // 添加的调用总是安全的,因为 `Vec` 永远不会分配超过 `isize::MAX` 字节。
        let dst_ptr = dst.as_mut_ptr().add(dst_len);
        let src_ptr = src.as_ptr();

        // 截断 `src` 而不丢弃其内容。
        // 我们首先执行此操作,以避免在 panics 处出现问题时避免出现问题。
        src.set_len(0);

        // 这两个区域不能重叠,因为可变引用没有别名,并且两个不同的 vectors 不能拥有相同的内存。
        ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);

        // 通知 `dst` 现在包含 `src` 的内容。
        dst.set_len(dst_len + src_len);
    }
}

let mut a = vec!['r'];
let mut b = vec!['u', 's', 't'];

append(&mut a, &mut b);

assert_eq!(a, &['r', 'u', 's', 't']);
assert!(b.is_empty());
Run