【问题标题】:Where C++ calls destructors?C++ 在哪里调用析构函数?
【发布时间】:2015-08-13 18:51:49
【问题描述】:

假设MemberMyList 是两个用户定义的类。在以下代码中:

void fillList(MyList &list1)
{
    Member m1("aaa");
    Member m2("bbb");
    list1.insert(m1);
    list1.insert(m2);   
}

void func1()
{
    MyList lst;
    fillList(lst);
    lst.printAll();
}

int main()
{
    func1();
    return 0;
}

C++ 在什么时候调用m1m2lst 的析构函数?

假设 C++ 不会删除将再次使用的对象总是安全的吗?

【问题讨论】:

  • 为什么不运行它?这似乎是用几个打印语句来验证的微不足道的事情。
  • Is it always safe to assume C++ does not remove an object which will be used again? 否。但这种情况是否有效取决于您的插入方法。
  • @Quirliom 认真的吗? SO有很多关于“UB哪些有效”的问题..
  • @deviantfan 其实我需要知道它来设计insert :)
  • @sermin 正如下面的 cmets 中所说,如果 insert 没有引用(void insert(Member m) 但不是 void insert(Member &m))那么没关系,因为在传递时会复制该值。当m1m2 被删除时,插入的副本将保留在列表中的某个位置。如果因为insert 没有复制它而使用引用和指针来引用已删除的对象,那么这很糟糕。

标签: c++ class memory-management destructor


【解决方案1】:

C++在什么时候调用m1、m2、lst的析构函数?

析构函数在作用域的末尾被调用,与对象定义的顺序相反。在您的情况下,首先调用func1(),定义lst,然后调用fillList(),定义m1m2。接下来fillList() 结束,所以现在m2 然后m1 析构函数被调用(以它们声明的相反顺序)。最后func1() 结束,所以lst 析构函数被调用。

假设 C++ 不会删除将再次使用的对象总是安全的吗?

我不太明白你的意思。一个被破坏的物体已经消失了,你不能再使用它了。尝试访问它(通过悬空指针/引用)只是未定义的行为。

【讨论】:

  • 这是否意味着printAll 会侵犯已销毁的m1 和m2 的内存?
  • @sermin insert() 是否进行引用,并且没有在内部创建副本?那么问题来了。
  • @sermin 如果insert 复制对象,那么一切都很好。如果它改为使用引用,那么您最终会得到悬空引用,这很糟糕。但大多数insert 函数实际上是在复制。在你的情况下最好复制,否则你就有麻烦了。
【解决方案2】:

在其作用域结束时调用析构函数(如果分配在“堆栈”上)或手动调用其delete 运算符(如果动态分配)。

至于您的其他问题,绝对假设任何此类事情都是安全的。 C++ 很乐意让你用你喜欢的钝锯锯断你自己的腿。在此过程中,它可能会询问您是否想要一些小猫形状的创可贴(您必须自己制作),但仅此而已。

【讨论】:

  • 最后一部分将是我的新 Skype 离开消息。
  • 几乎提到为你把创可贴放在高架子上,但我觉得有点暗。
猜你喜欢
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 2014-05-03
  • 2016-10-28
  • 1970-01-01
  • 2017-12-12
  • 2021-07-19
  • 2017-04-28
相关资源
最近更新 更多