memmove能安全处理内存重叠是因为它根据源和目标地址关系自动选择正向或反向拷贝,避免覆盖未读数据;memcpy则假设无重叠而直接正向拷贝,重叠时行为未定义。

memmove 为什么能安全处理内存重叠
因为 memmove 内部做了方向判断:当目标地址在源地址之后且存在重叠时,它会从内存末尾开始反向拷贝;否则正向拷贝。而 memcpy 假设内存不重叠,直接正向拷贝,重叠时就会把还没读取的原始数据覆盖掉。
数组内移动元素必须用 memmove,不能用 memcpy
常见场景比如删除数组中某个元素后,要把后面的元素前移;或者插入时腾出空间——这些操作都会导致源和目标区域重叠。
- 错误写法:
memcpy(arr + i, arr + i + 1, (n - i - 1) * sizeof(int))—— 重叠时行为未定义,可能丢数据 - 正确写法:
memmove(arr + i, arr + i + 1, (n - i - 1) * sizeof(int)) - 注意:
memmove第三个参数是字节数,不是元素个数,别漏乘sizeof(T) - 即使源和目标完全相同(如
memmove(p, p, n)),它也是安全的,而memcpy不保证
memmove 的参数顺序和空指针检查
参数顺序是 memmove(dest, src, n),和 memcpy 一致,容易混淆但不用记错——它只是更“宽容”。但它不检查空指针,传入 nullptr 仍会崩溃。
- 必须确保
dest和src都指向有效内存(或都为nullptr且n == 0) -
n为 0 时安全,可用来做空操作占位,比如某些条件分支里统一调用 - 不要指望它帮你做类型安全检查:对
std::vector或对象数组,它只按字节搬,不调用构造/析构函数
替代方案:C++ 中更推荐用 std::move 或算法
纯 C 风格数组用 memmove 没问题,但 C++ 容器或可移动类型,优先考虑标准库工具。
- 对
std::vector<int></int>,删中间元素用erase(it),底层已处理重叠 - 对 POD 类型数组,
std::move(arr + i + 1, arr + n, arr + i)更语义清晰,且支持迭代器、类型推导 -
std::move(算法版)和memmove行为等价,但类型安全,编译期可查错 - 非 POD 类型(含析构函数)绝对不能用
memmove,会跳过生命周期管理,引发未定义行为
重叠拷贝本身不复杂,难的是判断什么时候真有重叠、什么时候该换更高层抽象——尤其混用 raw 数组和容器时,边界容易算错。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











