我在C ++应用程序中遇到错误,我在调试时遇到问题。我已经在网上看了,我似乎正在以正确的方式完成所有的分配/释放。这是我的代码:
template <typename T>
class Matrix
{
private:
int _rows;
int _cols;
T** _matrix;
public:
Matrix(int r, int c);
~Matrix();
T GetValue(int r, int c);
};
template <typename T>
Matrix<T>::Matrix(int r, int c)
{
_rows = r;
_cols = c;
_matrix = new T*[_rows];
for(int i = 0; i < _rows; i++)
_matrix[i] = new T[_cols];
for(int i = 0; i < _rows; i++)
for(int j = 0; j < _cols; j++)
_matrix[i][j] = NULL;
}
template <typename T>
Matrix<T>::~Matrix()
{
for(int i = 0; i < _rows; i++)
delete [] _matrix[i];
delete [] _matrix;
}
template <typename T>
T Matrix<T>::GetValue(int r, int c)
{
if(r < 0 || r >= _rows || c < 0 || c > _cols)
{
throw -1;
return NULL;
}
return _matrix[r][c];
}
我的客户代码......
int main()
{
Matrix<int> myMatrix(3, 3);
myMatrix.GetValue(1, 1);
// myMatrix.~Matrix(); // Don't do this anymore
}
变量“myMatrix”超出范围后,我收到此错误:
0x103159da处于未处理的异常(msvcr1000d.dll)...访问冲突读取位置0xfeeefee2。
我被带到文件“dbgdel.cpp”
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead-&GT; nBlockUse));
请帮忙!
编辑:
好的,我忽略了提供一些信息。请参阅以下内容:
我有一个名为“T Dot(Matrix)”的附加方法我还有两个名为“Columns()”和“Rows()”的方法,它们只是_cols和_rows的getter。还有一个名为“SetValue(int r,int c,T value)”的方法,用于设置_matrix[r][c] = value
。我不认为显示实施是必要的。
template <typename T>
T Matrix<T>::Dot(Matrix<T> m)
{
if(_cols > 1 || m.Columns() > 1 || _rows != m.Rows())
{
throw -1;
return NULL;
}
T value = 0;
for(int i = 0; i < _rows; i++)
{
value += _matrix[i][0] * m.GetValue(i, 0);
}
return value; // Whoops, this was here, just forgot to type it
}
客户......
int main()
{
Matrix<int> intM1(3, 1);
Matrix<int> intM2(3, 1);
intM1.SetValue(0, 0, 1);
intM1.SetValue(1, 0, 1);
intM1.SetValue(2, 0, 1);
intM2.SetValue(0, 0, 1);
intM2.SetValue(1, 0, 1);
intM2.SetValue(2, 0, 1);
std::cout << intM1.Dot(intM2) << endl;
}
这会产生与上面相同的错误,但仅在调用“Dot()”函数时才会生成。
答案 0 :(得分:3)
不要显式调用析构函数,你已经在堆栈上分配了myMatrix
,因此当变量超出范围时,dtor
将被自动调用,即main()
回报。
答案 1 :(得分:2)
通过编辑,这里的问题仍然是缺少复制构造函数和赋值运算符(请参阅我对上一个问题的回答)。问题是当你将Matrix
by值传递给一个函数时,调用复制构造函数来制作副本,但是由于你没有定义一个C ++将使用默认的复制构造函数,它只是浅复制。因此,您最终会得到一个新的Matrix
,它共享指向与旧Matrix
相同元素的指针。当这个新的Matrix
超出范围时,它的析构函数将触发,清理另一个Matrix
使用的数组。当原始Matrix
超出范围并被清理时,它将尝试删除已删除的数组,从而导致崩溃。
要解决此问题,您需要实现正确复制资源的复制构造函数和赋值运算符。有一个名为Rule of Three的经验法则,如果你有一个析构函数,你还需要一个复制构造函数和赋值运算符来防止这些类型的错误。尝试实现这些缺失的功能,看看问题是否清除。
答案 2 :(得分:1)
修改强>:
这是错误:
T Matrix<T>::Dot(Matrix<T> m);
这个函数应该返回T
并且它最终没有返回!!放,
return value;
应该解决。还有一些建议:您正在通过值Matrix<T> m;
传递,这很容易出错。因为复制的m
和原始intM2
都指向相同的_matrix
。因此,当m
超出范围时,它将delete[]
一切。当intM2
超出范围时,将再次删除相同的内存。再一次崩溃。
因此,您应始终指定复制构造函数(作为private
或使用正确的复制代码)。截至目前,将定义更改为,
T Matrix<T>::Dot(Matrix<T> &m); // pass `m` by reference
这将解决您的所有错误。 (您也可以选择const Matrix<T> &m
,因为您可能需要更改GetValue () const
。)