永发信息网

C++基础问题 析构函数调用

答案:1  悬赏:10  手机版
解决时间 2021-07-25 08:41
  • 提问者网友:谁的错
  • 2021-07-24 17:33

class Hasptr {
public:
Hasptr(int *p, int i):ptr(p),val(i) { }
~Hasptr() { std::cout << "~Hasptr() " <<std::endl; delete ptr; }

int *get_ptr() const { return ptr; }
int get_int() const { std::cout << val <<std::endl; return val; }

void set_ptr(int *p) { ptr = p; }
void set_int(int i) { val = i; }

int get_ptr_val() const { std::cout << *ptr <<std::endl; return *ptr; }
void set_ptr_val(int val) const { *ptr = val; }


private:
int *ptr;
int val;
};

int main()
{

// #
int obj = 0;
Hasptr ptr1(&obj,42);
Hasptr ptr2(ptr1);
ptr1.set_int(0);
ptr2.get_int();
ptr1.get_int();
ptr2.set_ptr_val(22);
ptr1.get_ptr_val();
ptr2.get_ptr_val();
//如果把从#到这里的代码注释掉运行会出错,如果不注释掉则能运行,请问这是为什么?


int *ip = new int(44);
Hasptr ptr(0,10);
ptr.set_ptr(ip);
Hasptr ptrptr(ptr);
ptr.~Hasptr();
ptr.set_ptr_val(33);
ptrptr.set_ptr_val(33);
ptr.get_ptr_val();
ptrptr.get_ptr_val();
return 0;
}

最佳答案
  • 五星知识达人网友:佘樂
  • 2021-07-24 19:04

首先我想给您说以下,不是您说的您的#到您的中文解释那里的代码注释掉就不会出错,而是不管您注释不注释那上面的代码,它都会出错。


解释一下,我们就看下面的代码,您构造出来2个Hasptr类型的对象,这里一定得明白,这两个对象的ptr变量指向的是同一个地址,也就是您new出来的ip所指的地址。到程序运行结束需要析构这两个对象,按照构造的逆顺序,先析构ptrptr对象,在这个里面已经将ptr地址指向的内存释放,也就是将ip的指向的内存释放,之后又析构ptr对象,在这里又回去释放这个对象的ptr变量指向的内存,也是之前ip指向的内存,但是这个内存在之前已经被释放掉了,也就是一个悬空指针或者说是野指针,这里试图再次释放,所以说会出现错误。


如果类里面有成员变量是指针的话一定得注意。


可以自己写一下复制构造函数,代码如下


Hasptr(Hasptr& h)
{
ptr = new int;
*ptr = *(h.ptr);
val = h.val;
}


这个复制函数就负责将为自己重新开辟一个存放ptr的空间,与原对象指向的ptr地址不是同一个地址。


其实这里就涉及到了深拷贝,如果不懂可以加我QQ:810264。


谢谢采纳!

我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯