析构函数和Malloc'd成员

Ben*_*Ben 3 c++ malloc destructor new-operator delete-operator

让我们说,例如,我有一个类,需要使用一些旧的C东西(如pthreads或其他东西),所以出于某种原因,我最终在我的构造函数中调用了malloc(),就像所以:

class Foo
{
  public:
    Foo()
    {
      someMutex = malloc(sizeof(pthread_mutex_t));
      pthread_mutex_init(someMutex);
      someString = new string("yay string!");
    }

  private:
    pthread_mutex_t * someMutex;
    string * someString;
}
Run Code Online (Sandbox Code Playgroud)

似乎有很多关于析构函数的错误信息.我一直看到显式定义的析构函数调用delete基于指针的成员的示例,但我也继续阅读我不需要为类来管理内存显式定义析构函数; 我需要一个析构函数就像文件句柄清理之类的东西.

因此导致我的问题:即使someMutex分配了malloc而不是C++ new命令,隐式定义的析构函数是否仍会处理它,或者我是否必须这样做?

另外,让我们解决我的另一个问题,因为它的关系非常密切.在上面的类,我需要为了调用显式定义析构函数delete上的someString,或者是说对我的照顾?

Jam*_*lis 8

您不仅需要定义析构函数来进行清理,还需要为类声明(并可选地定义)复制构造函数和复制赋值运算符,以确保正确生成副本.

隐式定义的析构函数会破坏成员变量.因此,例如,如果您有一个类型的成员变量string,析构函数将自行销毁该变量.但是,指针的析构函数(如string*)是无操作:您负责销毁指向的对象.

您还需要为此类定义复制操作,或者至少禁止生成编译器为您提供的默认复制操作.为什么?因为默认情况下,复制操作只是复制每个成员变量.所以,例如,如果您要写:

{
    Foo x;
    Foo y(x);
}   // Uh oh
Run Code Online (Sandbox Code Playgroud)

二者xy在块的末尾销毁.在这一点上,两者xy指向同一个动态分配的互斥和字符串,所以互斥和字符串将被销毁两次(一次x和一次y).


更好的选择是根本不使用手动内存分配.相反,你应该成为类someString的直接成员(即声明它string someString;),或者你应该使用某种智能指针来管理它的生命周期(如unique_ptrshared_ptr).同样,您应该使用带有自定义删除器的智能指针来管理互斥锁的生命周期,除非您的类是不可复制的,在这种情况下,您可以使互斥锁成为该类的直接成员.