我有一个小问题…我知道EXC_BAD_ACCESS错误是什么,我通常知道如何修复它,但这一个已经让我完全填充。我把这些都放在一个类中,这里有一个方法:
double Matrix::get_element(int r, int c) const {
//Retrieve the element at row r and column c
//Should not modify the value stored in Matrix but return a double copy of the value
double currentValue = matrix[r][c];
return currentValue;
}
现在,我有另一段代码调用这个方法:
std::string Matrix::to_string() const {
std::string result;
double current;
Matrix working = *this;
std::ostringstream oss;
oss << "[";
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
current = 0.0;
current = working.get_element(i, j);
oss << " " << current << " ";
}
oss << "; ";
}
oss << "]";
result = oss.str();
return result;
}
我知道工作对象在调用working.get_element(i, j);
的地方有3行和3个颜色。变量列表显示,在get_element()
方法之前,行和颜色都被设置为3。在该方法中,我能够得到get_element(0, 0)
的值,但不能得到get_element(0, 1)
的值。
编辑:下面是头文件:
class Matrix {
private:
//Any variables required
int rows;
int cols;
double **matrix;
public:
Matrix(); //Working M
~Matrix(); //Working M
Matrix(int r, int c); //Working M
int getRows();
int getCols();
void set_element(int r, int c, double val); //Working M
double get_element(int r, int c) const; //Working M
void clear(); //Working M
bool is_empty(); //Working M
bool is_identity(); //Working M
const Matrix transpose(); //Working M
int minorMat(double **dest, const int row, const int col, int order); //Working M
double get_determinent(); //Working M
double higherDeterminents(int order); //Working M
const Matrix operator+(const Matrix &rhs); //Working M
const Matrix operator-(const Matrix &rhs); //Working M
const Matrix operator*(const Matrix &rhs);
bool operator==(const Matrix &rhs); //NOT assessed
const Matrix operator*(const double &rhs);
const Matrix operator/(const double &rhs);
Matrix & operator=(const Matrix &rhs);
std::string to_string() const;
};
请忽略注释,对不起。这是构造函数/析构函数:
Matrix::Matrix() {
//Basic Constructor
rows = 1;
cols = 1;
matrix = new double*[rows];
for (int i = 0; i < rows; ++i) {
matrix[i] = new double[cols];
}
}
Matrix::~Matrix() {
//Basic Deconstructor
for (int i = 0; i < rows; ++i) {
delete[] matrix[i];
}
delete[] matrix;
rows = NULL;
cols = NULL;
matrix = NULL;
}
Matrix::Matrix(int r, int c) {
//Empty matrix (all 0's) with r rows and c columns, if they are -ve, set to 1
rows = r;
cols = c;
if (cols < 0)
cols = 1;
if (rows < 0)
rows = 1;
matrix = NULL;
matrix = new double*[rows];
for (int i = 0; i < rows; i++) {
matrix[i] = new double[cols];
}
}
EDIT2:
Matrix & Matrix::operator=(const Matrix &rhs) {
//rhs is matrix to be copied
//rhs compied into Matrix called on
double toCopy;
for (int i = 0; i < rhs.rows; i++) {
for (int j = 0; j < rhs.cols; j++) {
toCopy = rhs.get_element(i, j);
this->set_element(i, j, toCopy);
}
}
return *this;
}
如果您没有说明如何声明和初始化matrix
元素,我们就不可能说出来。在您的CTOR中使用类似的内容应该没问题:
class Matrix {
float matrix[3][3];
...
}
别忘了在你的CTOR中把它初始化为有意义的东西。
Btw:你为什么这样做:Matrix working = *this;
??您可以简单地使用this->get_element(i, j);
,这样就不会调用对整个对象的复制。[1]
编辑:更新,因为你更新了你的答案。您应该小心使用您的复制ctor和operator=()
语句。很容易进行双重删除或诸如此类的丑陋操作。
EDIT2:我认为问题出在这一行:
Matrix working = *this;
您正在创建this
对象的新副本working
。但是working
初始化时只有1列和1行(如标准CTOR中定义的那样)。我不确定您是否在调用set_element
或get_element
时检查边界,所以我猜您正在编写数组的边界。
我认为最好的主意是删除Matrix working = *this;
行,并坚持我上面的提示:this->get_element(i, j);
in std::string Matrix::to_string() const
.
您的Matrix(int r, int c)
为matrix
分配内存,但保留其指向的值未初始化。在构造函数中添加如下内容:
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
this->set_element(i, j, 0);
}
}
这样做:
int main()
{
Matrix m(3,3);
std::cout << m.to_string();
}
输出: [ 0 0 0; 0 0 0; 0 0 0; ]
.
默认构造函数也一样:
Matrix::Matrix() {
//Basic Constructor
rows = 1;
cols = 1;
matrix = new double*[rows];
for (int i = 0; i < rows; ++i) {
matrix[i] = new double[cols];
}
}
您分配了内存,但是无论matrix[0][0]指向哪里,它都是未初始化的垃圾值。如matrix[0][0] = 0;
或任何你想要的默认值。
希望对你有帮助。
你的课违反了"三巨头"规则。如果一个类有析构函数、赋值操作符或复制构造函数中的一个,那么很可能需要同时拥有这三个。
在您的例子中,您有析构函数,但没有赋值操作符或复制构造函数,这将在执行Matrix working = *this
时创建UB条件。
从评论看来,您认为
new double[size]
将初始化元素为0,这是不正确的。你的大部分代码在技术上是非常糟糕的。使用
std::vector
而不是指针和动态内存来正确实现矩阵类会容易得多(代码更少)。当然,如果这只是一个练习,那么避免使用std::vector
是有意义的。
顺便说一下,如果你从来没有听说过"三大"规则,那么你很可能是在尝试通过实验来学习c++,而不是通过阅读。
对于c++,这不是一个明智的举动…逻辑可以用来代替学习,如果1)话题是高度逻辑的,2)如果你能告诉你什么时候你错了。
相反,c++非常非常复杂,在一些地方也非常不合逻辑(由于历史原因),所以有些部分逻辑会简单地误导你。
此外,当你在c++中犯错误时,你通常不会得到一个错误消息,而是"未定义的行为"。这基本上使得通过实验学习c++变得非常非常困难,因为即使是错误的代码也可能显然有效。也很容易写出看起来不错的代码,但实际上却因为一些微妙的原因而完全错误。
不要只是做实验,你应该找一本好书,从头到尾读一遍…