小心指针被delete两次

C++类中,有时候使用到传值调用(对象实体做参数),遇到这种情况,可要小心了!特别是当你所传值的对象生命周期较长,而非临时对象(生命周期段)的时候。来看看下面的情况:

#include <iostream>
using namespace std;
 
class Text
{
private:
     char  * str;
 
public :
     Text(){str = new char [20];::memset(str,0,20);}
     void SetText( char  * str)
     {
         strcpy(this->str,str);
     }
     char  * GetText() const{ return  str;}
     ~Text()
     {
         cout << "~Text Destruction"  << endl;
         delete  [] str;
         cout << "~Text Over"  << endl;
     }
};
 
void Print(Text str)
{
     cout << str.GetText() << endl;
}
 
int  main()
{
     Text t;
     t.SetText( "abc" );
     Print(t);
     return  1;
}

上面执行的结果程序崩溃了。原因:

Print(Text str)在对str进行复制构造的时候,没有进行深度拷贝;当 Print退出的时候,因为是临时对象(函数初始时构造),对str进行析构,此时还没有任何破绽;但回到main,继而退出main 的时候,又对t进行析构,但此时t内的str中的内容已经被销毁。由于对一内存空间实施了两次销毁,于是出现内存出错。

解决方法:

    1. 重写浅拷贝。像一下版本,不同的情况要作出适当的调整: 
      #include <iostream>
      using  namespace  std;
       
      class  Text
      {
      private :
           char  * str;
       
      public :
           Text(){str = new  char [20];:: memset (str,0,20);}
           Text(Text &t)
           {
               str = new  char [20];
               strcpy (str,t.GetText());
           }
           void  SetText( char  * str)
           {
               strcpy ( this ->str,str);
           }
           char  * GetText() const { return  str;}
           ~Text()
           {
               cout << "~Text Destruction"  << endl;
               delete  [] str;
               cout << "~Text Over"  << endl;
           }
      };
       
      void  Print(Text str)
      {
           cout << str.GetText() << endl;
      }
       
      int  main()
      {
           Text t;
           t.SetText( "abc" );
           Print(t);
           return  1;
      }
    2. (推荐)不使用传值调用。就像下面书写如下Print版本: 
      void  Print(Text &str)
      {
           cout << str.GetText() << endl;
      }
    3. 除非对象内所有的成员读属非指针内存内容,那么谨慎使用文章前面的用法。

转载于:https://www.cnblogs.com/candl/p/3813293.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值