所以我有一个名为MatrixMxN的类,在构造函数中它有参数row,column。我正在尝试为尺寸为row,column的2D数组分配内存,尽管我这样做有问题。 (我重写括号运算符以为每个条目赋值)
{
MatrixMxN coord(4, 1);
coord(0, 0) = 1.0;
coord(0, 1) = 1.0;
coord(0, 2) = 1.0;
coord(0, 3) = 1.0;
}
我遇到的问题似乎是在调用解构器时我收到错误: -
Windows已在MatrixTest.exe中触发断点。 这可能是由于堆的损坏,这表明MatrixTest.exe或它已加载的任何DLL中存在错误。
我的矩阵类的片段如下;
typedef float* floatPtr;
class MatrixMxN {
private:
float** entry;
int rows;
int cols;
public:
MatrixMxN(int r, int c) {
rows = r;
cols = c;
//Create a matrix
if(rows > 0 && cols > 0) {
//Declare an array of pointers
entry = new floatPtr[rows];
//Declare each array
for(int i=0; i<rows; i++) {
entry[i] = new float[cols];
}
this->empty();
}
}
~MatrixMxN() {
//Free memory
for(int i=0; i<rows; i++) {
delete[] entry[i];
}
//Free pointers array
delete[] entry;
}
void empty() {
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
entry[i][j] = 0;
}
}
}
// Assignment operator
void operator=(MatrixMxN& other) {
//Check they are the same size
assert(rows == other.rows && cols == other.cols);
//Copy
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
entry[i][j] = other(i, j);
}
}
}
float& operator()(const int irow, const int icol) {
//Check they are not out of bounds
assert ( (irow >= 0 && irow < rows) || (icol >= 0 && icol < cols) );
return entry[irow][icol];
}
...
绊倒错误的部分是在循环内的解构函数中;
//Free memory
for(int i=0; i<rows; i++) {
delete[] entry[i];
}
dbgheap.c文件在第一次尝试删除[] entry [i]时抛出错误,其中i = 0。虽然在打印矩阵时它按预期工作正常,但这里似乎有错误。希望我在这里提供了足够的信息,谢谢。
Edit1:包含赋值运算符重载 Edit2:Included()重载
答案: 问题是我是以转置的方式输入值而不是我的方式。感谢所有帮助,记忆在这里被破坏了。
答案 0 :(得分:3)
您应该一步分配内存:分配一个M * N浮点数组,然后计算每次访问时的访问位置。 您的释放同样简单:删除[]矩阵;
答案 1 :(得分:3)
您的类可能会泄漏内存并且行为未定义
你有一个大而邪恶的错误:你错过了一个合适的拷贝构造函数。编译器将为您生成一个正确的东西:复制指针。但那不是你想要的;相反,您的复制构造函数应分配新内存并复制数组的内容。
换句话说:使用当前的实现,您很容易泄漏内存并进行双重删除。
选择:
std::vector
),它们具有良好定义的复制语义并自行管理其内存。当你拥有的只是标准容器时,你甚至根本不需要析构函数和复制构造函数和复制赋值(如果你不以多态方式删除矩阵类)另外,风格建议:不要像这样使用empty
。所有标准容器都有一个empty()
方法,它可以完全不同于您的方法。
答案 2 :(得分:2)
你的empty()方法遍历行和行而不是行和列。这是破坏内存,当您删除条目时会捕获该内存。
在分配元素时,您可能也会破坏内存,因为在您的示例中,您的索引会被转置:
coord(0, 0) = 1.0;
coord(0, 1) = 1.0;
coord(0, 2) = 1.0;
coord(0, 3) = 1.0;
不是吗?
coord(0, 0) = 1.0;
coord(1, 0) = 1.0;
coord(2, 0) = 1.0;
coord(3, 0) = 1.0;
答案 3 :(得分:2)
这可能不是原因,但没有为类MatrixMxN
定义复制构造函数或赋值运算符:通过声明它们private
来定义它们或使对象不可复制。
虽然不是此示例中的问题,但如果delete[]
只有rows > 0
,则会在析构函数中的未初始化指针上调用cols <= 0
。在构造函数中,entry
仅在rows > 0 && cols > 0
时才会被初始化。如果rows > 0
但cols <= 0
,析构函数中的以下for
循环仍会调用delete[] entry[i];
:
for(int i=0; i<rows; i++) {
delete[] entry[i]; // entry unitialized
}
接下来是:
delete[] entry; // entry unitialized
编辑:
assert
中的operator()
不正确:
assert ( (irow >= 0 && irow < rows) || (icol >= 0 && icol < cols) );
它应该使用&&
:
assert ( (irow >= 0 && irow < rows) && (icol >= 0 && icol < cols) );