多个构造函数的析构函数

Destructor for multiple constructors

本文关键字:析构函数 构造函数      更新时间:2023-10-16

c++中有两个构造函数和一个析构函数。当我使用第一个构造函数为我的对象的析构函数被调用删除A[],这是我想要的,但当我使用第二个构造函数时,我不需要调用析构函数,但c++编译器调用它无论如何会导致错误。解决这个问题的最好方法是什么?

Tree(int n) {
  A = new int[n];
}
Tree(int data*, int n) {
   A = data;
}
~Tree(){
   delete [] A;
}

存储一个标志,指示析构函数是否应该调用delete。

注意,在手动管理内存时,还需要用户定义的复制构造函数和复制赋值操作符。

您需要使用c++ 03中的三规则或c++ 11中的五规则来避免此问题。

通常是一个糟糕的设计,在这种情况下,区分你是否拥有动态分配的缓冲区的唯一方法是通过一个布尔标志成员,如果你是分配内存的人,你必须在构造函数中设置。然后,在删除析构函数之前,检查是否有此标志,并仅在设置了该标志时才进行释放。

Tree(int n) 
{
  A = new int[n];
  OwnFlag = true;
}
Tree(int data*, int n) 
{
   A = data;
   OwnFlag = false;
}
~Tree()
{
  if(OwnFlag)
      delete [] A;
}

上面的代码只是一个使用布尔标志的演示,您仍然需要遵循规则。我已经发布了链接,这有助于你理解它是什么,我不发布代码在这里,因为我不希望你只是复制粘贴(我不说你会如果我添加代码,但你知道以防万一)。

在我看来这是一个有严重缺陷的设计。对象创建后,您不知道是否对内存负责。

设置一个标志,表明你是否拥有a中的数据,并在析构函数中检查它,以确定是否应该释放它。

一般来说,在c++中明确定义对象的所有权是很好的;显式设置可以防止内存泄漏。考虑让类始终是它所包含的对象的所有者,并让它负责销毁对象,无论它是如何创建的。

在第二个构造函数中,您正在分配pointer to an array。我建议您在第二个构造函数中创建heap(分配n个元素),并将参数(data)中的所有元素复制到新创建的heap中。

如果可能值得考虑使用两个不同的类:

struct basic_tree { 
    virtual ~basic_tree();
};
// Warning: incomplete -- at the very least, this almost certainly needs to 
// define its own assignment operator and copy ctor (aka the rule of three), 
// or else declare them private to prevent them (or use `=delete` in C++11).
// 
class owning_tree : public basic_tree { 
     int *A;
public:
     owning_tree(int n) : A(new int[n]) {}
     ~owning_tree() { delete [] A; }
};
class non_owning_tree : public basic_tree {
    int *A;
public:
    non_owning_tree(int *data) : A(data) {}
};

这既有优点也有缺点。一方面,一旦创建了正确类型的对象,其他的一切都将由类型系统自动处理。另一方面,这意味着您必须在构造时指定正确的类型,而不仅仅是传递正确类型的参数。这也意味着大多数树操作需要使用指向basic_tree的指针或引用,而不能直接使用树对象。根据具体情况,这可能完全没有问题(例如,如果树通常足够大,您通常会通过引用传递),也可能是一个大问题,例如添加大量额外的代码以在创建时对正确的类型进行排序。