C++易混点——深度解析指针悬挂和虚析构函数

来源:互联网 发布:深圳网络问政平台 编辑:程序博客网 时间:2024/05/17 06:44

1.指针悬挂及解决要点

1.1.何为指针悬挂:

指针悬挂值得是我们在程序的浅层拷贝过程中,因为默认的拷贝构造函数的局限性,导致的内存泄漏(至于泄露了那一部分内存,马上讲解),再长时间的积累下,每一次使用该函数的该复制 的特性,那么电脑中的内存就会丢失一块,长时间下来,导致电脑崩溃的事故发生,这一点对于C++这种没有Java垃圾内存回收机制的语言来说是开发中非常致命的一个大问题

1.2.泄露了那一部分内存:

当我们进行浅层拷贝的时候,电脑知识默认的将后者 的内存地址复制过去,使得两个指针对应的内存指向是相同的,那么之前一个内存不就变成了“野”内存,没有任何一个指针指向他,也就是说,我们永远无法找到那个内存区域,当然我们也就丢失了对他的控制了,这片内存就泄露了出去
代码举例:
class test{public://test(){//}//~test(){ //}void set(int p){key=&p;}void get(){printf("%d\n",*key);}private:int* key;};int main(){test b,a;  b=a;     //b原本key指向的内存有可能会丢失return 0;}
另一个错误,在我们调用异构函数的时候一旦我们采用这种浅层的拷贝,那么当一个析构完之后,另一个因为指向是相同的,但是该片内存已经释放过了,重复释放也会导致错误

1.3.如何避免:

我们目前避免这种情况的方法就是对等于号“=”进行运算符重载,我们重载的功能就是,在进行同等的复制的时候,我们先将原内存清理释放(可能会泄露的那块内存释放掉),然后再开批一个新的内存,对内存的额内容进行复制,从而防止上面的两个错误
示例代码如下:
#include"cstdio"#include"cstdlib"#include"cstring"#include"iostream"using namespace std;class errornull{};class test{public:test(){key=NULL;}~test(){ free(key);}void set(int& p)   //注意必须加引用,否则我们指向的只是为了复制而开辟的随机的内存{key=&p;}void get(){printf("%d\n",*key);}test& operator=(test& k){if(&k==this) return *this;    //特殊情况,如果是本身复制的话,直接返回就好else{try{if(k.key==NULL) throw errornull();if(key==NULL);    else delete key;    //释放内存     key=new int;    //重新开辟     *key=*k.key;    //手动复制     return *this; }catch(errornull e){cout<<"正在尝试复制不存在的内容"<<endl;} } }private:int* key;};int main(){test b,a;int s=3;a.set(s);a.get();b=a;b.get();return 0;}


2.虚析构函数

2.1.虚析构函数的必要性:

我们一旦了解过多态的话都会知道(如果没有学过多态,请自行百度)
我们完全可以通过基类的指针来动态创建(或者直接指向一个已经存在过的)一个新的子类的对象,这里就是多态的一个优点
但是在析构函数这里(动态创建的情况下会出现),回出现一些麻烦的问题
首先我们都知道一个规则,就是继承的时候的构造的顺序:
构造:先基类后子类
析构:先子类后基类
代码里面好说一点:
#include"iostream"#include"cstdio"#include"cstdlib"using namespace std;class a{public:a(){}~a(){}private:int key;};class b:public a{public:b():a(){}~b(){}private:int oh;};int main(){a* my;my=new b;  //在这里我们析构的话我们没有用 虚 来实现多态的控制的话,那么我们之后自动delete my的时候,调用的只是my的析构函数,我们//就相当于把子类b忘了,忘了析构子类,这时候必然会导致错误,所以我们致力的继承中析构函数都是用 虚 的,目的就是用指针析构的是真正的指向的子类,而不是子类中嵌套包含的基类的那一部分,而是子类全部//换句话说,我们的目的是调用子类的析构函数而不是基类的析构函数,这时候的virtual,虚析构函数的作用就和我们当时多态的一样了,自然就达到了我们所谓的删除了我们想删除的东西的目的 return 0;}

3.参考文献

gaozhegfeng的博客
Kevin1993year的博客
寒星轩的博客
1 0
原创粉丝点击