C++ 析构函数导致程序崩溃
我真的很难理解将析构函数与复制构造函数结合使用的概念。如果我不使用析构函数,代码工作正常,因为它会自动执行。如果我这样做,我会得到一个错误,说“调试断言失败!”和“表达式:\块\类型\有效(pHead->nBlockUse) 但我想了解如何使用析构函数。这是下面的代码,我将非常感谢帮助解释我做了什么错误或需要做什么C++ 析构函数导致程序崩溃,c++,copy-constructor,C++,Copy Constructor,我真的很难理解将析构函数与复制构造函数结合使用的概念。如果我不使用析构函数,代码工作正常,因为它会自动执行。如果我这样做,我会得到一个错误,说“调试断言失败!”和“表达式:\块\类型\有效(pHead->nBlockUse) 但我想了解如何使用析构函数。这是下面的代码,我将非常感谢帮助解释我做了什么错误或需要做什么 类矩阵{ private: int M; int N; double *data; public: Matrix(); int getM()
类矩阵{
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);
}
private:
int M;
int N;
双*数据;
公众:
矩阵();
int getM()常量{return M;}
int getN()常量{return N;}
//建造师
矩阵(int sizeR、int sizeC、双*输入数据)
{
M=sizeR;//行
N=sizeC;//列
data=new double[M*N];//创建1D数组,使用M&N值
cout在复制构造函数中复制指针,这意味着您现在有两个对象都具有相同的指针。如果其中一个对象被解构,那么另一个对象将保留一个无效指针
无论如何,取消引用此指针或尝试释放它都会导致错误
有问题的一行是:
M1 = Matrix(M1);
该行创建一个临时对象,并将数据从M1
复制到该临时对象中,然后将临时对象分配回M1
(编译器生成的复制赋值操作符将只对成员进行浅层复制,与复制构造函数没有太大区别)然后销毁临时对象,导致M1
中的指针丢失且无效
关于一个稍微相关的问题,您可能还想了解。您正在复制构造函数中将一个对象的指针复制到另一个对象中:
Matrix(const Matrix& oldMatrix)
{
...
data = oldMatrix.data;
调用复制构造函数后,有两个对象引用同一个memoryblock。如果一个对象被破坏,则内存块将被删除,第二个对象指向无效的内存位置
在复制构造函数中,您还需要分配一个新的缓冲区!解决方案可能是向矩阵类添加一个bool变量(例如is\u copy
)。在构造函数中将其设置为false,在复制构造函数中设置为true。只有在is\u copy为false时才解除析构函数中的内存分配
或者,正如评论中所建议的,最好使用智能指针。有多少次是new[]
被调用?有多少次是delete[]
被调用?设置data=oldMatrix。复制构造函数中的data1
看起来非常可疑!!!仅供参考,它是析构函数,而不是解构函数。我还对代码进行了一点缩进和解构。不要害怕空白。data
应该是vector
,不要使用原始指针这不是解决方案-它只会增加更多问题。如果第一个对象被销毁,但副本仍然存在怎么办?使用布尔标志无法解决所有权和间接寻址问题。这就是为什么我说“可能”。有时,您希望进行浅层复制,而不能简单地通过引用传递矩阵。如果您的原始对象打算在整个程序执行过程中存活下来,则没有problem@NoelPerezGonzalez智能指针可以解决这个问题,正如@WojtekSurowka所说,布尔值不能解决它。std::shared\u ptr
或boost::shared_ptr
。然而,我只会在数据为const
@tilart时使用这种共享方法。你是对的。还有很多次(比如CUDA)在这里,你不能使用智能指针。但是这超出了问题的范围。“NoelPrErgZZalez我不认为应该使用这样的解决方案。在正常的C++用法中,复制对象是安全的,或者复制是不允许的。你提出一个只有在特殊情况下才能工作的技巧,当某人添加时,就要自找麻烦。s是一个返回对象的函数。只有在需要时才应使用此类技巧,即使这样也不应像您建议的那样隐藏。请使用另一个函数而不是复制构造函数,或者以其他方式使缓冲区共享更为明显,使其显式化。我可以建议改为使用零规则吗