-- 一个困扰小李的程序问题
背景说明:
某日,小李同事(以前KS老同事)在Q群里喊了一个程序问题……正好当时我没啥事就关注关注,了解并跟进了问题……结果,帮忙调到了出现问题地方。话说这种问题虽然不算高深,但是比较微妙可能很多C++程序猿都曾类似地犯错过。鉴于这一点,所以我就在此小小博文一篇,谨此提醒C++朋友们少犯类似的错误吧。
问题描述:
Debug版本程序必崩,而Release版本运行正常。程序崩溃在main函数语句mat2 = (mat+mat1);
问题原因:
程序没有定义Matrix类型的拷贝构造函数,在调用函数operator+之后,其返回值Matrix对象析构了指针mat指向的数据,而导致函数外部使用其返回值无效,这样使得Debug版程序崩溃;而为什么函数Release版程序运行正常呢,原因在于程序经编译器优化,使得函数operator+返回值Matrix对象与函数外使用的属于同一对象,即不析构函数operator+内的局部变量,让其对象继续在函数外使用,这样程序运行就正常了。具体的细节设计C++对象模型,相关的详细知识参见《C++对象模型》。
解决方案:
正确定义Matrix类型的拷贝构造函数。详见如下红色代码。
红色标记表示(添加)修改部分!
-- Matrix.h --
#include <iostream>
#include <cassert>
using namespace std;
template <class T>
class Matrix
{
private:
int col;
int row;
T **mat;
public:
Matrix() {}
Matrix(int col,int row);
virtual ~Matrix();
#include <iostream>
#include <cassert>
using namespace std;
template <class T>
class Matrix
{
private:
int col;
int row;
T **mat;
public:
Matrix() {}
Matrix(int col,int row);
virtual ~Matrix();
Matrix(const Matrix<T>& obj)
:col(obj.GetCol()), row(obj.GetRow())
{
assert (col >=0 && row >=0);
if (col && row)
{
mat=new T*[row];
for(int i=0; i<row; i++)
{
mat[i]=new T[col];
for (int j=0; j < col; ++j)
{
//mat[i][j] = (obj.getValue(i, j));
mat[i][j] = obj[i][j];
}
}
}
}
public://矩阵操作
T* operator[] (int index) const
{
return mat[index];
}
T getValue(int r, int c) const
{
return mat[r][c];
}
int GetCol()const;
int GetRow()const;
public://运算符重载
//一般运算符重载
Matrix& operator=(const Matrix<T>& matrix);
//二元运算符重载
template <class T>
friend Matrix<T> operator+(const Matrix<T>& left, const Matrix<T>& right);
Matrix operator-(const Matrix<T>& matrix);
public://数据获取
void GetData(const char* fileName);
void PrintMat();
private://工具函数
};
template <class T>
Matrix<T>::Matrix(int row,int col )
{
this->col=col;
this->row=row;
mat=new T*[row];
for(int i=0; i<row; i++)
{
mat[i]=new T[col];
}
}
template <class T>
Matrix<T>::~Matrix()
{
for(int i=0; i<row; i++)
delete [] mat[i];
delete [] mat;
}
template <class T>
int Matrix<T>::GetCol()const
{
return this->col;
}
template <class T>
int Matrix<T>::GetRow()const
{
return this->row;
}
template <class T>
void Matrix<T>::PrintMat()
{
for(int i=0; i<this->row; i++)
{
for(int j=0; j<this->col; j++)
{
cout << mat[i][j] << " ";
}
cout << endl;
}
}
template <class T>
void Matrix<T>::GetData(const char* fileName)
{
ifstream fileIn(fileName);
if(!fileIn)
{
cout << "Read Error!" << endl;
return;
}
for(int i=0; i<row; i++)
{
for(int j=0; j<col; j++)
{
fileIn >> mat[i][j];
}
}
fileIn.close();
}
template<class T>
Matrix<T>& Matrix<T>::operator=(const Matrix<T>& matrix)
{
if (this == &matrix)
return *this;
this->col=matrix.col;
this->row=matrix.row;
for(int i=0; i<row; i++)
{
for(int j=0; j<col; j++)
{
this->mat[i][j]=matrix.mat[i][j];
}
}
return *this;
}
template<class T>
Matrix<T> operator+(const Matrix<T>& left, const Matrix<T>& right)
{
Matrix<T> tmp(left.col, left.row);
for(int i=0; i<left.row; i++)
{
for(int j=0; j<left.col; j++)
{
tmp.mat[i][j]=left.mat[i][j]+right.mat[i][j];
}
}
return tmp;
}
template<class T>
Matrix<T> Matrix<T>::operator-(const Matrix<T>& matrix)
{
if(this->col!=matrix.col||
this->row!=matrix.row)
{
cout << "Can not add the matrixs!" << endl;
}
Matrix<T> tmp(this->col, this->row);
for(int i=0; i<this->row; i++)
{
for(int j=0; j<this->col; j++)
{
this->mat[i][j]=this->mat[i][j]-matrix.mat[i][j];
}
}
return tmp;
}
#endif
-- main.cpp --
#include "matrix.h"
int main(void)
{
Matrix<int> mat(3,3);
mat.GetData("SourceData.txt");
mat.PrintMat();
Matrix<int> mat1(3,3);
mat1.GetData("SourceData.txt");
mat1.PrintMat();
Matrix<int> mat2(3,3);
mat2 = (mat+mat1);
mat2.PrintMat();
std::cout << "hello world.\n";
return 1;
}
没有评论:
发表评论