c++中隐藏的共享内存片段带来的致命错误

先看一段类定义代码

class CMessage
{
private:
char * m_pMessage;
public:

//构造函数
CMessage(const char * text = "Default message"){
  size_t length{ strlen(text) + 1 };
  m_pMessage = new char[length+1];
  strcpy_s(m_pMessage,length,text);
 };
~CMessage(){
cout<<"已释放m_pMessage成员指向的内存"<<endl;
delete []m_pMessage;
}

void  show()const
{
cout<<m_pMessage<<endl;
}

};

现在我们在main函数里实现复制
int main(void)
{
char *p{"We are the winner"};
CMessage p1{p};
CMessage p2{p1};    //默认复制构造函数
p1.~CMessage();   //显示调用析构函数用于释放p1的成员占用的内存

p2.show();            //输出p2的m_PMessage

return 0;
}

运行结果:



错误分析:

由于默认复制构造函数的作用是将类对象p1的指针成员储存的地址复制到p2中,因为默认构造函数是值传递,所以这两个对象共享了一个地址的字符串。所以p1中m_PMessage占用的内存被释放后p2的也被释放了,所以p2.show()出来的是一串乱码。而且会听到咚咚咚的 声音,这个窗口要关掉都会卡一下。


如果不显式调用析构函数:

int main(void)
{
char *p{"We are the winner"};
CMessage p1{p};
CMessage p2{p1};    //默认复制构造函数

p2.show();            //输出p2的m_PMessage

return 0;
}
运行结果:


运行成功,但是会伴随熟悉的咚咚咚的声音,窗口关闭卡顿问题,主要是默认复制构造函数会存在内存的问题。

这就是默认复制构造函数的隐藏风险,这时候就需要自定义复制构造函数了。

在类的public中加入下面的自定义函数:

CMessage(const CMessage& aMess){
  size_t len{strlen(aMess.m_pMessage)+1};
  m_pMessage = new char[len];
  strcpy_s(m_pMessage,len,aMess.m_pMessage);
 }

main函数:

int main(void)
{
 char * p{"We are the winner"};
 CMessage p1{ p };
 CMessage p2{p1};   //调用了自定义复制构造函数

p1.~Cmessage();     //显式调用析构函数释放p1占用的内存空间
 p2.show();
 return 0;
}

运行结果:


分析:

至于为什么会调用了三次析构函数呢,我们这里先不讨论,显示调用析构函数会出现这些问题,如果想具体了解显示调用带来的影响可以去博客查一下。现在我们只看p2中的m_pMessage,看这个运行结果显示这时p2中的m_pMessage没有受到影响,这说明p1和p2没有共享一段内存空间。

如果这时不显示调用析构函数呢

main函数:

int main(void)
{
 char * p{"We are the winner"};
 CMessage p1{ p };
 CMessage p2{p1};   //调用了自定义复制构造函数

 p2.show();
 return 0;
}

运行结果:


分析:

结果完美,由系统自己去调用析构函数还是更好啊,没有出现内存的一些问题。


当然,结合上面4个实例,这时你会想那如果修改p1中的m_pMessage,会不会带来类似的结果。

这里就需要读者自己去实验咯。

给你布置个小作业就是写个函数如下

void display(CMessage pol)    

{

pol.show();

return;

}

你看完这段代码可能会觉得很正常啊,可是我们写这个函数都是习惯了用引用或者指针的方式去传入,这次这个是传值,

空闲储存器中就有了相同的一个副本。给你一个小提示:析构函数的隐式调用是在类对象超出了它的作用域时自动调用的。

欧吼,这是第一次写博客,希望大佬别喷,当然可以提意见,最后希望这些内容对大家学习有帮助。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值