C/C++八股文:说清楚memcpy和memmove
memcpy和memmove是C/C++中常用的内存拷贝函数,关键区别在于处理内存重叠的能力。memcpy假定源和目标不重叠,速度快但重叠时行为未定义;memmove则支持安全处理重叠情况,通过方向感知拷贝避免数据破坏,性能略低但更安全。对于非平凡类型对象,两者都不安全,应使用其他拷贝方式。若无重叠保证优先用memcpy,否则必须用memmove。
·
C/C++八股文:说清楚memcpy和memmove
一句话结论
memcpy
假定源和目标不重叠(重叠是 UB),更快;memmove
支持重叠拷贝(定义良好),通常比 memcpy
稍慢但安全。
关键区别(要点)
-
重叠行为
memcpy(dest, src, n)
:当dest
与src
所指的区域有重叠时,行为未定义(UB)。memmove(dest, src, n)
:当两个区域重叠时有定义的语义,结果相当于先把源区的n
字节临时保存再复制到目标(或等价的方向感知复制),不会破坏数据。
-
API(签名)
void *memcpy(void *dest, const void *src, size_t n); void *memmove(void *dest, const void *src, size_t n);
都在
<string.h>
/<cstring>
中,返回dest
。 -
实现策略(常见)
memcpy
:直接按机器字(word)或更大向量块正向拷贝,尽可能用最速路径(SIMD/memcpy 内建)。编译器在知道无重叠时可用更激进优化。memmove
:先检查dest
与src
的相对位置:- 若
dest < src
:从低地址向高地址正向拷贝(安全)。 - 若
dest > src
且有重叠:从高地址向低地址反向拷贝(避免覆盖还没拷贝的源字节)。
也有实现会在小拷贝时把数据拷到内部临时缓冲区,但通常采用方向感知拷贝即可避免额外空间。
- 若
-
性能
- 在不重叠情况下,
memcpy
通常最快。 memmove
需要额外判断(或可能使用更保守的路径),因此平均可能稍慢;但现代库/编译器优化良好,差距可能很小。- 如果编译器能证明无重叠,它可能把
memmove
优化为memcpy
。
- 在不重叠情况下,
-
语义层面(C vs C++)
- 在 C++ 中,对 非平凡(non-trivially-copyable)对象 使用
memcpy
/memmove
通常是不安全/未定义的(会破坏对象语义、破坏 vptr、打破构造/析构契约)。对 POD / trivially-copyable 类型(例如纯数据结构或std::byte
数组)才安全。对对象请用std::copy
, 移动构造或序列化方法。
- 在 C++ 中,对 非平凡(non-trivially-copyable)对象 使用
-
特殊情况
- 如果
n == 0
,标准允许某些实现接受NULL
指针(但要小心,最好传有效指针或保证 n>0)。 - 返回值相同:两者都返回
dest
,便于链式调用(虽然不常用)。
- 如果
重叠会出错的 memcpy
:
char buf[] = "0123456789";
// 试把起始 5 字节向左移 2 字节:结果期待 "2343456789" 还是?
// 使用 memcpy 是 UB,通常会得到错误结果
memcpy(buf, buf + 2, 5);
printf("%s\n", buf); // 未定义,可能是破坏的数据
同样场景用 memmove
(安全):
char buf[] = "0123456789";
memmove(buf, buf + 2, 5); // 正确:会把 "23456" 移到起始位置
printf("%s\n", buf); // 输出 "2345656789"(按实现)
一种简单的伪代码
void *memmove(void *dest, const void *src, size_t n) {
unsigned char *d = dest;
const unsigned char *s = src;
if (d < s) {
// 正向拷贝
for (size_t i = 0; i < n; ++i) d[i] = s[i];
} else if (d > s) {
// 反向拷贝
for (size_t i = n; i-- > 0; ) d[i] = s[i];
}
return dest;
}
人话
memcpy
:快,但重叠 UB。memmove
:安全处理重叠(方向感知或临时缓冲),稍慢。- 对对象语义敏感的类型不要用这两者(非 trivially-copyable)。
- 如果能保证不重叠用
memcpy
;若不确定或可能重叠用memmove
。
更多推荐
所有评论(0)