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

时间:2019-07-04 22:51:42

标签: c++ destructor

我试图理解为什么在以下代码中调用析构函数。

我想函数f()会以某种方式触发析构函数,但我不知道为什么。

#include <iostream>
using namespace std;

class c {
    int* p;

public:
    c() { p = new int(1); }
    void display() { cout << *p << endl; }
    ~c() { delete p; }
};

void f(c){};

void main() {
    c o;
    f(o);
    o.display();
    getchar();
}

输出为-572662307,最后,抛出该运行时异常:CrtIsValidHeapPointer(block)。调用了析构函数,并删除了该特定地址的指针。

1 个答案:

答案 0 :(得分:1)

f()的输入参数通过值获取,因此,在调用o时会生成f(o)副本 。当f()退出时,副本超出范围时将被破坏。

您的c类没有定义副本构造函数副本分配运算符,因而违反了Rule of 3。因此,c内的复制的 f()对象将最终持有与p中的o对象相同的main()指针值。销毁副本后,其析构函数将释放int,将o中的main()留下指向无效内存的悬挂指针,随后对o.display()的调用将具有不确定的行为。您需要在c类中实现适当的复制语义:

class c {
    int* p;

public:
    c() { p = new int(1); }
    c(const c &src) { p = new int(*(src.p)); }
    ~c() { delete p; }

    c& operator=(const c &rhs) { *p = *(rhs.p); return *this; }

    void display() const { cout << *p << endl; }
};