为什么我以前调用析构函数的方式会导致内存问题?
why would the way I used to call destructor cause memeory issue?
在下面的代码中,如果我将 dealloc_dMAT 包含到析构函数中,它不起作用。但是如果我专门调用 dealloc_dMAT 然后调用析构函数,它就可以工作。为什么会这样?我使用的编译器是linux.
下的g++ 4.8.2
下面的代码不起作用,
#include <iostream>
using namespace std;
class QO{
public:
QO();
~QO();
int DIM;
double **dMAT;
void alloc_dMAT();
void dealloc_dMAT();
};
QO::QO(){
DIM=4;
cout << "DIM=" << DIM << endl;
alloc_dMAT();
}
QO::~QO(){
dealloc_dMAT();
}
void QO::alloc_dMAT(){
dMAT=new double * [DIM];
for(int i=0; i<DIM; i++) dMAT[i]=new double [DIM];
}
void QO::dealloc_dMAT(){
for(int i=0; i<DIM; i++) delete [] dMAT[i];
delete [] dMAT;
}
int main(){
QO QB;
//QB.dealloc_dMAT();
QB.~QO();
return 1;
}
但稍微修改一下就可以了
#include <iostream>
using namespace std;
class QO{
public:
QO();
~QO();
int DIM;
double **dMAT;
void alloc_dMAT();
void dealloc_dMAT();
};
QO::QO(){
DIM=4;
cout << "DIM=" << DIM << endl;
alloc_dMAT();
}
QO::~QO(){
//dealloc_dMAT();
}
void QO::alloc_dMAT(){
dMAT=new double * [DIM];
for(int i=0; i<DIM; i++) dMAT[i]=new double [DIM];
}
void QO::dealloc_dMAT(){
for(int i=0; i<DIM; i++) delete [] dMAT[i];
delete [] dMAT;
}
int main(){
QO QB;
QB.dealloc_dMAT();
QB.~QO();
return 1;
}
编辑:感谢 Dave M. 的评论,上面的代码似乎没有完全显示我的问题,所以这里是我 运行 遇到的麻烦的更准确的例子。如果你编译并 运行 它,你会注意到代码在 i=0 处中止,如果 ~QO 仅在退出 main 时被调用两次,则不会发生这种情况。
#include <iostream>
#include <stdlib.h>
using namespace std;
class QO{
public:
QO();
~QO();
int DIM;
double **dMAT;
void alloc_dMAT();
void dealloc_dMAT();
};
QO::QO(){
DIM=4;
cout << "DIM=" << DIM << endl;
alloc_dMAT();
}
QO::~QO(){
dealloc_dMAT();
}
void QO::alloc_dMAT(){
dMAT=new double * [DIM];
for(int i=0; i<DIM; i++) dMAT[i]=new double [DIM];
}
void QO::dealloc_dMAT(){
for(int i=0; i<DIM; i++) delete [] dMAT[i];
delete [] dMAT;
}
int main(){
for(int i=0; i<10; i++){
QO QB;
QB.~QO();
cout << "i= " << i << endl;
}
system("pause");
return 1;
}
总的来说,我建议您像这样评论显式析构函数调用:
for(int i=0; i<10; i++)
{
QO QB;
//QB.~QO();
cout << "i= " << i << endl;
}
然后你像这样向析构函数添加一个cout
:
QO::~QO()
{
dealloc_dMAT();
cout << "destructor called.";
}
这会让您清楚地知道您不需要显式调用析构函数,因为每次退出 for
作用域时都会隐式调用它。
也 dMAT
指针是 delete
之后的悬挂指针,因此通常将其分配给 nullptr
是一个很好的做法,尽管在某些情况下它可能没有效果,例如删除后立即退出指针范围,因为指针本身不再存在。
在下面的代码中,如果我将 dealloc_dMAT 包含到析构函数中,它不起作用。但是如果我专门调用 dealloc_dMAT 然后调用析构函数,它就可以工作。为什么会这样?我使用的编译器是linux.
下的g++ 4.8.2下面的代码不起作用,
#include <iostream>
using namespace std;
class QO{
public:
QO();
~QO();
int DIM;
double **dMAT;
void alloc_dMAT();
void dealloc_dMAT();
};
QO::QO(){
DIM=4;
cout << "DIM=" << DIM << endl;
alloc_dMAT();
}
QO::~QO(){
dealloc_dMAT();
}
void QO::alloc_dMAT(){
dMAT=new double * [DIM];
for(int i=0; i<DIM; i++) dMAT[i]=new double [DIM];
}
void QO::dealloc_dMAT(){
for(int i=0; i<DIM; i++) delete [] dMAT[i];
delete [] dMAT;
}
int main(){
QO QB;
//QB.dealloc_dMAT();
QB.~QO();
return 1;
}
但稍微修改一下就可以了
#include <iostream>
using namespace std;
class QO{
public:
QO();
~QO();
int DIM;
double **dMAT;
void alloc_dMAT();
void dealloc_dMAT();
};
QO::QO(){
DIM=4;
cout << "DIM=" << DIM << endl;
alloc_dMAT();
}
QO::~QO(){
//dealloc_dMAT();
}
void QO::alloc_dMAT(){
dMAT=new double * [DIM];
for(int i=0; i<DIM; i++) dMAT[i]=new double [DIM];
}
void QO::dealloc_dMAT(){
for(int i=0; i<DIM; i++) delete [] dMAT[i];
delete [] dMAT;
}
int main(){
QO QB;
QB.dealloc_dMAT();
QB.~QO();
return 1;
}
编辑:感谢 Dave M. 的评论,上面的代码似乎没有完全显示我的问题,所以这里是我 运行 遇到的麻烦的更准确的例子。如果你编译并 运行 它,你会注意到代码在 i=0 处中止,如果 ~QO 仅在退出 main 时被调用两次,则不会发生这种情况。
#include <iostream>
#include <stdlib.h>
using namespace std;
class QO{
public:
QO();
~QO();
int DIM;
double **dMAT;
void alloc_dMAT();
void dealloc_dMAT();
};
QO::QO(){
DIM=4;
cout << "DIM=" << DIM << endl;
alloc_dMAT();
}
QO::~QO(){
dealloc_dMAT();
}
void QO::alloc_dMAT(){
dMAT=new double * [DIM];
for(int i=0; i<DIM; i++) dMAT[i]=new double [DIM];
}
void QO::dealloc_dMAT(){
for(int i=0; i<DIM; i++) delete [] dMAT[i];
delete [] dMAT;
}
int main(){
for(int i=0; i<10; i++){
QO QB;
QB.~QO();
cout << "i= " << i << endl;
}
system("pause");
return 1;
}
总的来说,我建议您像这样评论显式析构函数调用:
for(int i=0; i<10; i++)
{
QO QB;
//QB.~QO();
cout << "i= " << i << endl;
}
然后你像这样向析构函数添加一个cout
:
QO::~QO()
{
dealloc_dMAT();
cout << "destructor called.";
}
这会让您清楚地知道您不需要显式调用析构函数,因为每次退出 for
作用域时都会隐式调用它。
也 dMAT
指针是 delete
之后的悬挂指针,因此通常将其分配给 nullptr
是一个很好的做法,尽管在某些情况下它可能没有效果,例如删除后立即退出指针范围,因为指针本身不再存在。