为什么我以前调用析构函数的方式会导致内存问题?

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 是一个很好的做法,尽管在某些情况下它可能没有效果,例如删除后立即退出指针范围,因为指针本身不再存在。