如何在二维数组的拷贝构造与赋值运算符中使用memcpy?
如何在两种二维float数组实现类中使用memcpy完成拷贝构造与赋值重载
因为float是POD(普通旧数据)类型,内存布局简单可直接拷贝,所以完全可以用std::memcpy替代逐元素循环赋值,提升拷贝效率。以下针对两个类分别说明实现方式:
一、UsingPtrToArr类(指向固定宽度数组的指针)
该类的二维数组是连续内存块,new float[m_rows][8]会分配一块连续的内存空间,所有行数据依次排布,因此可以直接一次性拷贝整个数组内存。
修改后的拷贝构造函数
UsingPtrToArr(const UsingPtrToArr& iv) { m_rows = iv.m_rows; f = new float[m_rows][8]; // 一次性拷贝所有行数据,内存连续无需逐行处理 std::memcpy(f, iv.f, m_rows * 8 * sizeof(float)); sum = iv.sum; }
修改后的赋值运算符重载
注意:必须先处理自赋值,再释放旧内存,避免内存泄漏与悬挂指针
UsingPtrToArr& operator= (const UsingPtrToArr& iv) { if (this == &iv) return *this; // 防止自赋值 // 释放旧内存 delete[] f; m_rows = iv.m_rows; f = new float[m_rows][8]; std::memcpy(f, iv.f, m_rows * 8 * sizeof(float)); sum = iv.sum; return *this; }
二、UsingPtrToPtr类(指向指针的指针)
该类的每行内存是独立分配的,指针数组f中存储的是每行内存的地址,整个二维数组的内存不连续,因此只能逐行使用memcpy拷贝。
修正并修改后的拷贝构造函数
原代码循环从i=1开始会遗漏第一行数据,需改为从i=0开始:
UsingPtrToPtr(const UsingPtrToPtr& iv) { sum = iv.sum; m_rows = iv.m_rows; m_cols = iv.m_cols; f = new float*[m_rows]; for(int i = 0; i < m_rows; ++i) { f[i] = new float[m_cols]; // 逐行拷贝连续的列数据 std::memcpy(f[i], iv.f[i], m_cols * sizeof(float)); } }
修正并修改后的赋值运算符重载
同样需要处理自赋值与旧内存释放,同时修正原代码中释放内存的循环起始错误:
UsingPtrToPtr& operator= (const UsingPtrToPtr& iv) { if (this == &iv) return *this; // 自赋值检查 // 释放旧内存:必须遍历所有行 for (int i = 0; i < m_rows; ++i) { delete[] f[i]; } delete[] f; // 分配新内存并逐行拷贝 m_rows = iv.m_rows; m_cols = iv.m_cols; f = new float*[m_rows]; for(int i = 0; i < m_rows; ++i) { f[i] = new float[m_cols]; std::memcpy(f[i], iv.f[i], m_cols * sizeof(float)); } sum = iv.sum; return *this; }
关键注意事项
- 仅当元素类型为POD时,使用
memcpy才安全。float属于POD,若替换为自定义非POD类型(如包含自定义构造/析构函数的类),memcpy会导致浅拷贝,引发未定义行为。 - 赋值运算符必须处理自赋值场景,否则会在释放旧内存后导致自身数据丢失。
内容的提问来源于stack exchange,提问作者Sourabh
相关产品推荐
相关产品推荐

