C++中的指针悬挂问题(内存泄漏)

我们知道赋值运算符是双目运算符,如果用户没有自定义赋值运算的函数,那么系统将自动生成一个默认的对象赋值运算符使对象能够赋值,比如有两个对象c1(10,20),c2;执行赋值运算的时候:c2=c1;在这里,赋值运算的执行没有问题,它能够像基本数据类型的赋值一样赋值,然而,C++中提供给对象的默认的赋值运算符并不是万能的,看这么一个例子:
#include"stdafx.h"
#include<iostream>
using namespace std;
class STRING
{
public:
STRING(char *s)
{
cout<<"构造函数执行中..."<<endl;
p=new char[strlen(s)+1];
strcpy(p,s);
}
~STRING()
{
cout<<"析构函数执行中..."<<endl;
delete []p;
}
private:
char *p;
};
int main()
{
STRING a("book");
STRING b("jeep");
b=a;
return 0;
}

在这里例子中,看起来好像没什么问题,其实不然,程序在运行的时候创建了两个对象,分别是a和b,然后调用构造函数,通过运算符new分别从内存中动态的分配了一块空间,并且使指针p指向该空间,这时,两个动态空间的字符串分别为“book”和“jeep”见下图(1)所示。调用构造函数在屏幕中显示“构造函数执行中...”。当执行“b=a”的时候,因为没有用户自己定义的赋值运算符函数,于是程序自动调用默认的赋值函数,出现了如图(2)的情况,两个指针指向了同一个内存,“jeep”这个空间的内存应经不能访问了。当程序执行到析构函数,释放内存时,先撤销b,释放了b指向的内存,接着在释放a,然而,虽然a的指针还在,但是,因为它与b指向的是同一内存即存放“book”的内存,又由于“book”的内存空间已经被执行析构b的时候释放掉,现在执行a在此释放,无法找到要释放的内存,并且,之前b指向的内存即“jeep”还没有释放掉,析构函数找不到它在哪里?指针p也没有空间可以指向,悬挂起来了。此时,就出现了所谓的“指针悬挂问题”。



由于C++能够操作计算机里面的内存,它不想JAVA等运行于虚拟机的语言,不用自己考虑内存的释放。如果用C++开发一个软件,没当软件运行一次,指针就悬挂一次,内存又丢失了一个,长期下去,那么,计算机的内存就会塞满,从而使你的计算机运行得越来越慢,严重时会导致系统崩溃。那么,如何来解决这个问题?答案就是重载赋值运算符“=”,使不但能够拷贝数据成员,并且以为对象a和b分配各自的内存空间,这就是所谓的深层拷贝,看下面的例子:
#include"stdafx.h"
#include<iostream>
using namespace std;
class STRING
{
public:
STRING(char *s)
{
cout<<"构造函数执行中..."<<endl;
p=new char[strlen(s)+1];
strcpy(p,s);
}
~STRING()
{
cout<<"析构函数执行中..."<<endl;
delete []p;
}
//重载赋值运算符“=”
STRING&STRING::operator=(const STRING&s);
private:
char *p;
};
STRING&STRING::operator=(const STRING&s)
{
if(this==&s)
return *this;
delete []p;
p=new char[strlen(s.p)+1];
strcpy(p,s.p);
}
int main()
{
STRING a("book");
STRING b("jeep");
b=a;
return 0;
}
在这个程序中就解决了“指针悬挂”问题,程序开始运行,创建两个对象a和b,分别调用构造函数,开了内存空间给两个对象分别存放“book”和“jeep”。此时会在屏幕中输出“构造函数执行中...”,执行“b=a”时,由于已经定义了赋值重载运算符函数,于是就调用重载的运算符函数。在重载运算符函数里面,执行delete []p把p指向的“jeep”空间先释放掉,再为p开辟另外一个空间,然后把a拷贝到p新开的空间里面去。当程序在结束的时候执行析构函数的时候,就把a和b的空间都释放掉了,从而很就解决了“指针悬挂”问题。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值