我试图理解为什么在以下代码中调用析构函数。
我想函数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)。调用了析构函数,并删除了该特定地址的指针。
答案 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; }
};