博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
小心指针被delete两次
阅读量:6845 次
发布时间:2019-06-26

本文共 1413 字,大约阅读时间需要 4 分钟。

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

你可能感兴趣的文章