C++ operator=重载后程序运行崩溃问题求助
C++调试崩溃问题:浅拷贝引发的内存错误
问题描述
代码在Dev++中编译通过,但调试运行时崩溃。核心疑惑:想要通过memcpy(array,ar.getArray(),r*c*sizeof(array[0][0]))实现值拷贝(深拷贝),但实际触发了浅拷贝逻辑,导致程序崩溃。
错误现象
运行时触发内存访问错误,程序崩溃(对应原错误截图的崩溃场景)
待排查代码
#include<iostream> #include<cstdlib> using namespace std; class Array2 { private: int r; int c; int **array; public: Array2 (){ cout<<"无参构造函数"<<endl; //k=1; } Array2 (int row,int colume); ~Array2() { if(array) { cout<<"析构函数被调用!"<<endl; for(int i=0;i<r;++i) { delete [] array[i]; } delete [] array; } } int * operator [] (int & i); int & operator () (int & i,int & j); Array2 & operator = ( Array2 & ar); void setR(int row){ r=row; } void setC(int colume){ c=colume; } int getR() { return r; } int getC() { return c; } int** getArray() { return array; } }; Array2 & Array2:: operator = ( Array2 & ar){ cout<<"赋值运算符重载"<<endl; r=ar.getC(); c=ar.getR(); array=new int*[r*c]; for(int i=0;i<r;i++){ array[i]=new int[c]; } memcpy(array,ar.getArray(),r*c*sizeof(array[0][0])); return *this; } int & Array2:: operator () (int & i,int & j){ return array[i][j]; } int * Array2:: operator [] (int & i){ //return a[i]; return array[i]; } Array2:: Array2(int row,int colume ):r(row),c(colume) { cout<<"有参构造函数"<<endl; array=new int*[r]; for(int i=0;i<r;i++){ array[i]=new int[c]; } } int main() { Array2 a(3,4); int i,j; for(i=0;i<3;++i) { for(j=0;j<4;j++) { a[i][j]=i*4+j; } } for(i=0;i<3;++i) { for(j=0;j<4;++j) cout<<a(i,j)<<", "; cout<<endl; } cout<<"next"<<endl; Array2 b; Array2 c(3,4); b=a; for(i=0;i<3;++i) { for(j=0;j<4;++j) cout<<b(i,j)<<", "; cout<<endl; } if(&a==&b) cout<<"a和b的地址相同"<<endl; else { cout<<"a和b的地址不同"<<endl; cout<<"a:"<<a.getArray()<<", "<<"b:"<<b.getArray()<<endl; } if(&a!=&c) cout<<"a和c的地址不同"<<endl; cout<<"a:"<<a.getArray()<<", "<<"c:"<<c.getArray()<<endl; return 0; }
问题根源与修复方案
1. 赋值运算符的行列值搞反
原代码中r=ar.getC(); c=ar.getR();完全颠倒了行和列的赋值,导致后续内存分配和拷贝逻辑全部错位。
修复:改为r=ar.getR(); c=ar.getC();
2. 二维数组指针数组分配错误
array=new int*[r*c];错误分配了r*c个指针,实际上二维数组的指针数组只需要r个元素(对应每行的起始指针)。
修复:改为array=new int*[r];
3. memcpy误用导致浅拷贝
直接用memcpy拷贝指针数组,会把原对象的每行指针地址复制过来,导致两个对象共享同一片内存区域。程序结束时,两个对象的析构函数会重复释放同一块内存,触发崩溃。
修复:逐行拷贝元素值,替换原memcpy语句:
for(int i=0; i<r; ++i){ memcpy(array[i], ar.getArray()[i], c*sizeof(int)); }
4. 无参构造未初始化指针
无参构造的array未初始化为nullptr,析构时可能访问野指针。
修复:在无参构造函数中添加array = nullptr;
5. 运算符重载参数的引用问题
operator[]和operator()的参数用int&会导致无法接收临时变量(比如字面量下标),引发编译或运行问题。
修复:改为值传递或const int&,例如:
int * operator [] (int i); int & operator () (int i,int j);
修正后的赋值运算符重载示例
Array2 & Array2::operator = (Array2 & ar){ cout<<"赋值运算符重载"<<endl; // 先释放当前对象已有的内存,避免内存泄漏 if(array){ for(int i=0;i<r;++i){ delete [] array[i]; } delete [] array; } // 正确赋值行列 r=ar.getR(); c=ar.getC(); // 正确分配指针数组 array=new int*[r]; for(int i=0;i<r;i++){ array[i]=new int[c]; // 逐行拷贝元素值 memcpy(array[i], ar.getArray()[i], c*sizeof(int)); } return *this; }
内容的提问来源于stack exchange,提问作者Andrew Liu
相关产品推荐
相关产品推荐

