memcpy拷贝数组时必须手动传入字节数,因数组名退化为指针后丢失长度信息;正确做法是用sizeof(array)计算总字节数,或对形参额外传入长度,目标内存须预先分配且足够大。

memcpy 拷贝数组时必须手动传入字节数
直接用 memcpy 拷贝数组,不会自动识别数组长度——它只认字节。C++ 中数组名退化为指针后丢失尺寸信息,所以你得自己算清楚要拷多少字节。
常见错误是写成 memcpy(dest, src, sizeof(src)),但 src 如果是函数参数(比如 int arr[] 形参),sizeof(src) 就是指针大小(通常 8 字节),不是原数组长度,结果只拷了前几个元素甚至越界。
- 正确做法:对栈上定义的数组,用
sizeof(array) / sizeof(array[0])算元素个数,再乘以单个元素字节数 - 若数组是函数参数,必须额外传入长度(或用
std::span、std::array替代裸数组) - 目标内存
dest必须已分配且足够大,memcpy不检查空间是否够用
int src[5] = {1, 2, 3, 4, 5};
int dest[5];
memcpy(dest, src, sizeof(src)); // ✅ 正确:sizeof(src) 是整个数组字节数
memcpy 拷贝多维数组要注意内存连续性
C++ 原生多维数组(如 int a[3][4])在内存中是连续的,可以整块拷贝,但必须按总字节数传参,不能只传 sizeof(a[0])。
容易踩的坑是当成「数组的数组」误以为要循环拷每行,其实没必要——只要确保目标空间布局一致,一调 memcpy 就完事。
-
sizeof(a)给出的是全部 3×4 个 int 的总字节数,可直接用 - 如果目标是
int b[3][4],那么memcpy(b, a, sizeof(a))完全合法 - 但如果目标是指向指针的指针(如
int** b),就不能用memcpy,那是非连续内存,得逐行分配+拷贝
替代 memcpy 的更安全选择:std::copy 和 std::array
裸 memcpy 在类型不匹配或重叠内存时行为未定义,且不调用构造/析构函数。对于类类型数组(含非平凡构造函数的对象),memcpy 可能导致资源泄漏或崩溃。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
推荐优先用 std::copy,它支持迭代器、类型安全、可处理重叠区域(用 std::copy_backward),还能配合 std::array 避免长度丢失问题。
-
std::array<int> a = {1,2,3,4,5}, b;</int>→std::copy(a.begin(), a.end(), b.begin()); - 对
std::vector同样适用,且自动管理内存 - 若必须用
memcpy(如高性能数值计算、POD 类型批量搬运),务必确认类型是 trivially copyable,并检查对齐和大小
memcpy 报错 “access violation” 或 “segmentation fault” 怎么定位
这类错误几乎都源于地址非法:源或目标指针为空、未初始化、越界、指向只读内存(如字符串字面量),或跨线程访问未同步的栈内存。
调试时不要只看 memcpy 调用行,重点查前后两步:指针怎么来的、有没有 malloc/new 失败未判空、有没有提前 free/delete 过。
- 用 AddressSanitizer 编译(
-fsanitize=address)能快速定位越界和 use-after-free - 对栈数组,确认没把局部数组地址返回给函数外使用
- 避免
memcpy(dst, "hello", 6)往字面量拷——目标必须是可写内存
真正麻烦的从来不是 memcpy 本身,而是你传给它的两个地址背后那一长串内存生命周期逻辑。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










