【问题标题】:Why does destructor create a bug when it's being called?为什么析构函数在被调用时会产生错误?
【发布时间】:2016-02-03 15:11:01
【问题描述】:

我创建了一个日历类,其中一切似乎都工作正常,但就在程序结束之前,当调用析构函数时,它会导致调试断言失败!

这是课程:

    //constructor
Calendar::Calendar(const int *pday, const int *pmonth, const int *pyear){
    day = new int(sizeof(pday));
    month = new int(sizeof(pmonth));
    year = new int(sizeof(pyear));

    day = pday;
    month = pmonth;
    year = pyear;
}

//copy constructor
Calendar::Calendar(const Calendar &rhs){
    day = new int(sizeof(rhs.day));
    month = new int(sizeof(rhs.month));
    year = new int(sizeof(rhs.year));

    day = rhs.day;
    month = rhs.month;
    year = rhs.year;
}

//operator '=' overload
Calendar& Calendar::operator=(const Calendar &rhs){
    delete[] day;
    delete[] month;
    delete[] year;

    day = new int(sizeof(rhs.day));
    month = new int(sizeof(rhs.month));
    year = new int(sizeof(rhs.year));

    day = rhs.day;
    month = rhs.month;
    year = rhs.year;

    return *this;
}

//deconstructor
Calendar::~Calendar(){
    delete[] day;
    delete[] month;
    delete[] year;
}

可能是什么问题?我不是为类的变量创建内存吗?

【问题讨论】:

  • 你为什么使用delete[]?为什么你完全使用指针而不是整数?
  • new[size] 也许?不是 new() 或只是删除
  • 为什么您的默认日期是 4/4/4 或 8/8/8?
  • 你真的应该从一个教程开始,如果可能的话,避免新的和删除的,直到你掌握其他概念......当你到达new时,它可能会在@987654324中变得很明显@,arg 与分配的内存大小无关。
  • 去掉sizeof(),使用delete代替delete []。虽然你根本不应该为这个类使用指针和动态分配。

标签: c++ class pointers memory destructor


【解决方案1】:

当您使用new 创建指针时,您使用delete 删除它。当你用new[] 创建一个指针时,你用delete[] 删除它。混合它们是未定义的行为,这就是你正在做的事情。您使用new 创建指针,但使用delete[] 删除它

我相信你的意思是创建像这样的指针

day = new int;
month = new int;
year = new int;

你为什么在这里使用指针?使用指针似乎不是这里的方法。一个简单的Calendar 类存储日、月、年,可以实现为

Calendar
{
private:
    int day_;
    int month_;
    int year_;
public:
    Calendar(int day = 0, int month = 0, int year = 0) : day_(day), month_(month), year_(year) {}
};

现在默认的复制构造函数、赋值运算符和析构函数将为您工作,并且没有指针需要处理。

【讨论】:

    【解决方案2】:

    让我们看看你的复制构造函数:

    Calendar::Calendar(const Calendar &rhs){
        day = new int(sizeof(rhs.day));
        month = new int(sizeof(rhs.month));
        year = new int(sizeof(rhs.year));
    
        day = rhs.day;
        month = rhs.month;
        year = rhs.year;
    }
    

    首先,您分配内存并将它们分配给您的成员。然后用rhs 对象中的指针覆盖该对象中的指针,导致两个对象都指向同一个内存。当其中一个对象被破坏时,其他对象将具有杂散指针,尝试删除它们将导致未定义的行为

    一种解决方案是使用解引用来复制值,例如

    *day = *rhs.day;
    

    但是我真的认为这里根本不需要指针,这意味着你不需要分配内存,你不需要担心复制,你不需要担心内存泄漏的杂散指针。事实上,如果您没有指针,您甚至不需要复制构造函数、赋值运算符或析构函数。我建议你阅读the rule of zero

    【讨论】:

      【解决方案3】:

      不,您没有正确构建数据。

      day = pday;
      month = pmonth;
      year = pyear;
      

      是一个指针赋值,从参数中复制地址,而不是它们的值。

      正确的方法是(假设我们要复制1个元素):

      *day = *pday;
      *month = *pmonth;
      *year = *pyear;
      

      您还将数组删除 delete[] 与单个元素 new 混合在一起(没有 [])。那是未定义的行为。

      还有一件事,day = new int(sizeof(pday)); 创建了一个 int,并使用一个指针大小的值进行了初始化。这看起来很奇怪。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-22
        • 2018-07-23
        • 2021-11-06
        • 2010-12-21
        • 2018-07-17
        • 2022-07-05
        • 2017-01-26
        相关资源
        最近更新 更多