我正在编写一个动态矩阵类,该类将每个非零值存储为3个元素的列表[行,列,值] 我制作了一个动态数组类,叫做“列表”,而“矩阵”类是一个列表指针的列表。
我的转置Matrix的代码有效:
void transpose(Matrix tripleList)
{
for (int i = 0; i < tripleList.getNumOfElem(); i++)
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
cout << "\n";
}
}
直接在main()中编写时可以工作,但在独立函数中会出错。谁能解释为什么以及如何解决?
完整代码:
#include <iostream>
using namespace std;
class List //a dynamic int pointer array
{
private:
int capacity;
int numOfElem;
int *arr;
//initialize all values in capacity to 0
void initialize(int from)
{
for (int i = from; i < capacity; i++)
{
arr[i] = 0;
}
}
//double the capaicty, then initialize
void expand()
{
capacity *= 2;
int *tempArr = new int[capacity];
for (int i = 0; i < numOfElem; i++)
tempArr[i] = arr[i];
delete[] arr;
arr = tempArr;
initialize(numOfElem);
}
public:
List()//constructor
{
capacity = 10;
numOfElem = 0;
arr = new int[capacity];
}
~List()//destrcutor
{
delete[] arr;
}
//add int to the end of List
void append(int newElement)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = newElement;
}
//Copy all element of an input list to the end of List
void copy(List list)
{
for (int i = 0; i < list.getNumOfElem(); i++)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = list.getAt(i);
}
}
//get reference of the int at an index in te list
int* getAddress(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return &arr[index];
}
//change the value of at specific index
void set(int index, int value)
{
arr[index] = value;
}
//get int at an index in te list
int getAt(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return arr[index];
}
int getNumOfElem()
{
return numOfElem;
}
void displayList()
{
for (int i = 0; i < numOfElem; i++)
{
cout << arr[i] << " ";
}
}
};
class Matrix //a List of list pointers
{
private:
int capacity;
int numOfElem;
List* *arr;
void initialize(int from)
{
for (int i = from; i < capacity; i++)
{
arr[i] = new List;
}
}
void expand()
{
capacity *= 2;
List* *tempArr = new List*[capacity];
for (int i = 0; i < numOfElem; i++)
tempArr[i] = arr[i];
delete[] arr;
arr = tempArr;
initialize(numOfElem);
}
public:
Matrix()
{
capacity = 10;
numOfElem = 0;
arr = new List*[capacity];
}
~Matrix()
{
delete[] arr;
}
void append(List* newElement)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = newElement;
}
void set(int index, List* value)
{
arr[index] = value;
}
List* getAt(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return arr[index];
}
int getNumOfElem()
{
return numOfElem;
}
};
void transpose(Matrix tripleList)
{
for (int i = 0; i < tripleList.getNumOfElem(); i++)
{
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
cout << "\n";
}
}
int main()
{
int m, n, input;
cout << "Please enter the number of rows and columns of the matrix :\n";
cin >> m >> n;
Matrix tripleListMatrix;
int k = 0;
cout << "Please enter the matrix : \n";
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> input;
if (input != 0)
{
tripleListMatrix.append(new List);
(*(tripleListMatrix.getAt(k))).append(i + 1);
(*(tripleListMatrix.getAt(k))).append(j + 1);
(*(tripleListMatrix.getAt(k))).append(input);
k++;
}
}
}
cout << "The triple list of matrix is:\n";
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
(*(tripleListMatrix.getAt(i))).displayList();
cout << "\n";
}
cout << "\n\n";
//transpose(tripleListMatrix);
//the code below is the same as in the function transpose but transpose gives error
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
//cout << "\t" << list;
cout << "\n";
}
cout << "\n\n";
//checking that tripleListMatrix is unchanged
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
(*(tripleListMatrix.getAt(i))).displayList();
cout << "\n";
}
return 0;
}
答案 0 :(得分:1)
列表* * arr;
调用transpose()
时,它会复制Matrix
,因为您没有通过引用传递。该副本仅具有列表的地址副本,而不是其自己的List
对象。当析构函数在副本上运行时,它将清除分配的内存,但是main中的原始Matrix对象仍指向该相同的内存。当该对象消失时,其析构函数将尝试再次释放相同的内存,这很糟糕。
您可能是说:
void transpose(Matrix const & tripleList)
这样,在调用transpose()
时不会产生任何副本,但是您也应该显式删除Matrix的副本构造函数,以便不能对其进行调用
Matrix(Matrix const &) = delete;
或创建一个显式的Matrix复制构造函数,以构造内存的深层副本。