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. 除非对象内所有的成员读属非指针内存内容,那么谨慎使用文章前面的用法。

小心指针被delete两次的更多相关文章

  1. C++ delete 两次

    转载自:http://blog.csdn.net/jxluofeng/article/details/19766801 <问题>危险的代码: int* p=new int(1);   de ...

  2. 问题:C++ 删除数组指针实用 delete []变量 汇编怎么实现的?

    问题:C++ 删除数组指针实用  delete []变量    汇编怎么实现的?

  3. 迷途指针 new delete

    编程中有一种很难发现的错误是迷途指针.迷途指针也叫悬浮指针.失控指针,是党对一个指针进行delete操作后——这样会释放它所指向的内存——并没有把它设置为空时产生的.而后,如果你没有重新赋值就试图再次 ...

  4. 《挑战30天C++入门极限》c++中指针学习的两个绝好例子

        c/c++中指针学习的两个绝好例子 对于众多人提出的c/c++中指针难学的问题做个总结: 指针学习不好关键是概念不清造成的,说的简单点就是书没有认真看,指针的学习犹如人在学习饶口令不多看多学多 ...

  5. C语言:指针实现交换两个变量的值

    用指针交换两个变量的值(10分) 题目内容: 用指针交换两个变量的值 主函数参考: int main( ) { int a,b; scanf("%d%d",&a,& ...

  6. C语言:通过函数指针来完成两个数的加减乘除(函数指针当做参数使用)

    // //  main.c //  Function_pointer // //  Created by mac on 15/8/2. //  Copyright (c) 2015年. All rig ...

  7. C语言:通过函数指针来完成两个数的加减乘除

    // //  main.c //  Function_pointer // //  Created by mac on 15/8/2. //  Copyright (c) 2015年. All rig ...

  8. C++ 指针 new delete int*与string

    一 指针 string和int 都可以认为是四个字节sizeof(string)==4, string是个类,它的空间在堆动态分配 二.delete 只是释放空间 三.new 数组 int size= ...

  9. mysql delete两种关联删除方式

    基本格式:  DELETE t1 FROM t1,t2 WHERE t1.id=t2.id 或 DELETE FROM t1 USING t1,t2 WHERE t1.id=t2.id  示例应用: ...

随机推荐

  1. Metrics.NET report to Zabbix

    废话不多说,先上git地址 https://github.com/binking338/Metrics.Reporters.ZabbixReporter 实现了Metrics.NET到Zabbix的报 ...

  2. Sublime Text 2 配置及其使用

    如果说Notepad++是一款不错Code神器,那么Sublime Text应当称得上是神器滴哥. Sublime Text最大的优点就是跨平台,Mac和Windows均可完美使用:其次是强大的插件支 ...

  3. win8下安装ubuntu双系统

    终于成功在win8下安装成功ubuntu13.10, 安装方法来源于http://forum.ubuntu.org.cn/viewtopic.php?t=446557 下面的文件是该楼主的将安装ubu ...

  4. line-height的小技巧

    CSS中的line-height属性控制着文字的行间距离.通常被设置为一个无单位的值(例如:line-height:1.4),与文字尺寸是成比例的.它是排版中的一个重要的属性.太低了文字会挤在一起,太 ...

  5. sql语句小练习一

    create database aaa go use aaa go create table student(    sno varchar(3), sname varchar(4) not null ...

  6. rel=nofollow

    nofollow是什么意思? nofollow是html标签的一个属性值,Google推荐使用nofollow,告诉机器(爬虫)无需追踪目标页,是指禁止蜘蛛爬行和传递权重,但是如果你是通过sitema ...

  7. setjmp 与 longjmp

    setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理. 先来看一下这两个函数的定义 ...

  8. C# 委托:把方法组合到一个数组中使用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  9. 2搭建Android开发环境

    这一章主要是讲解如何搭建Android开发环境,需要准备的工具有: (1)   JDK6或以上的版本: (2)   Eclipse (3)   ADT(用于开发Android应用程序) (4)   C ...

  10. PHP开发大型项目的一点经验

    一.变量 最好是把所有的变量存储在一个数组中,这样在程序的开发中可以带来很多的方便,特别是当程序很大的时候.变量的命名就当适合自己的习惯,不管是用拼音还是英语,至少应当有一定的意义,以便适合记忆.变量 ...