我真的在使用带有副本构造函数的析构函数的概念。如果我不使用析构函数,代码可以正常工作,就像它自动执行一样。如果我这样做,我会收到一条错误,说“调试断言失败!”和'表达式:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)。
但我希望能够理解如何使用析构函数。以下是下面的代码,我非常感谢帮助解释我做错了或者需要做什么! class Matrix {
private:
int M;
int N;
double *data;
public:
Matrix();
int getM() const { return M; }
int getN() const { return N; }
//CONSTRUCTOR
Matrix(int sizeR, int sizeC,double * input_data)
{
M = sizeR; //Rows
N = sizeC; //Columns
data = new double[M*N]; //creation of 1D array, uses m&n values
cout << "\nMatrix::Matrix(int sizeR, int sizeC, double * data_value) is invoked...\n\n";
//ENTER DATA INTO MATRIX HERE:
for(int i=0; i < M*N; i++) //Loops for every data entry into 1D array, uses r&c as referenece to
data[i] = input_data[i];//Accesses each value at specific location, inputs value 'val'
for(int i = 0; i < M*N; i++) //Loops for every data entry into 1D array, uses r&c as referenece to size
cout << data[i] << " ";
}
//get function uses row and column from user
double get(int i, int j)
{
return data[i*N+j];
}
double set(int i, int j, double val)
{
data[i*N+j] = val;
cout << "\n\nNEW MATRIX: ";
for(int i = 0; i < M*N; i++)//Loops for every data entry into 1D array, uses r&c as referenece to size
cout << data[i] << " ";
return val;
}
Matrix(const Matrix& oldMatrix)
{
cout¸<< "\nMatrix::Matrix(const Matrix&) is invoked....";
M = oldMatrix.getM();
N = oldMatrix.getN();
data = oldMatrix.data;
cout << "\n\n";
//ENTER DATA INTO MATRIX HERE:
for(int i = 0; i < M*N; i++)//Loops for every data entry into 1D array, uses r&c as referenece to size
cout << data[i] << " ";
}
//DESTRUCTOR
~Matrix()
{
//delete data
delete [] data;
data = NULL;
cout << "\n\nMatrix::~Matrix() is invoked...\n\n";
}
};
int main()
{
int sizeR, sizeC;
double val;
cout << "Enter No. Rows: ";
cin >> sizeR;
cout << "Enter No. Columns: ";
cin >> sizeC;
double * input_data;
input_data = new double[sizeR*sizeC];
//INPUTS VALUES TO ARRAY
for(int i = 0; i < sizeR*sizeC; i++)//Loops for every row
input_data[i] = i;
Matrix M1(sizeR, sizeC, input_data);
cout << "Enter row that value you are after is in: ";
cin >> sizeR;
cout << " & now the column that it is in: ";
cin >> sizeC;
cout << "Change value: " << M1.get(sizeR, sizeC) << " to:";
cin >> val;
M1.set(sizeR, sizeC, val);
//calls copy constructor
M1 = Matrix(M1);
}
答案 0 :(得分:4)
在复制构造函数中,您复制指针,这意味着您现在有两个具有相同指针的对象。如果其中一个对象被破坏,那么它会使另一个对象的指针无效。
无论如何取消引用此指针,或尝试释放它,都会导致undefined behavior。
有问题的问题是这一行:
M1 = Matrix(M1);
该行创建一个临时对象,并将数据从M1
复制到该临时对象中,然后将临时对象分配回M1
(以及编译器 - 生成的复制赋值运算符只会执行成员的浅表副本,因此与复制构造函数没有太大差别,然后破坏临时对象,导致M1
中的杂散和无效指针。
在一个稍微相关的问题上,您可能还想了解the rule of three。
答案 1 :(得分:0)
您正在复制构造函数中将一个对象的指针复制到另一个对象:
Matrix(const Matrix& oldMatrix)
{
...
data = oldMatrix.data;
调用复制构造函数后,您有两个对象引用相同的内存块。如果一个对象被破坏,则删除内存块,第二个对象指向无效的内存位置。
在复制构造函数中,您还需要分配一个新缓冲区!
答案 2 :(得分:-2)
解决方案可能是将一个bool变量(例如is_copy
)添加到Matrix类中。在构造函数上将其设置为false,在复制构造函数上将其设置为true。如果is_copy为false,则仅在析构函数中释放内存。
或者,正如评论中所建议的那样,最好使用智能指针。