博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++的构造函数和析构方面(拷贝构造函数)
阅读量:5355 次
发布时间:2019-06-15

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

头文件

class  student
{
public:
 student(char*);
 ~student();
 student(const student &);
 char* name;
 static int num;
};

 main.cpp文件

int  student::num=0;

student::student(char* myname)

{

num++;

int len=strlen(myname);

name=new char[len+1];

strcpy(name,myname);

cout<<name<<":创建,剩余个数:"<<num<<endl;

}

student::~student()

{

num--;

cout<<name<<":销毁,剩余个数:"<<num<<endl;

delete [] name;

}

void fun(student  funs)

{

cout<<funs.name<<"被调用"<<endl;

}

void main()

{

student stu1("student1");//--------------1

student stu2("student2");//--------------2

student stu3("student3");//--------------3

 

fun(stu2);//--------------4

student stu4=stu3;//--------------5

student stu5("student5");//--------------6

stu5=stu1;//--------------7

}

123都很正常,到4的时候,实参为类值对象,传递过程是一个拷贝构造函数,funs在fun方法结束后会调用析构函数,而运行到5的时候,这是一个通过拷贝构造函数实例化类,这个过程不会调用构造方法和析构函数的,因为我们要了解拷贝构造函数是如何写的,如下

student(const student & c)

{

name=c.name;

}

所以5就相当于 student stu4(stu3)

7的时候只是赋值,不是通过拷贝构造函数实例化类,因为stu5已经在6的时候实例化了

这个代码在VC 6.0中运行的时候,神奇般的出错了,第一个错误出在main函数结束后,一个个析构,堆栈的析构顺序是先进后出,先析构stu5,再析构stu4,再析构stu3,就在析构stu3的时候出错了。截图如下

为什么会出错,此时研究后发现是因为在5这个位置调用了拷贝构造函数来构造stu4类对象,根据拷贝构造函数的原型(下是原型)
student(const student & c)

{

name=c.name;

}

我发现name=c.name,对于5来说就是stu4.name=stu3.name;name是一个指针,这是一个指针赋值,即stu4name指针指向了stu3的那么指针指向的位置。那么问题迎刃而解了,即在析构stu4的时候(因为堆栈析构顺序先析构晚压入栈的),delete [] name了,就是告诉计算机,name这块内存被释放了,不被任何东西指向(不和任何东西有关系),于是再去析构stu3的时候,出问题了。。你已经和这块地址没有关系了,凭什么让你delete。而且也没必要delete了,但是如果你知道这块空间地址,并通过地址直接访问这块空间还是能访问到name的值的,因为值并没有被删除,修改代码后,你会更加明白问题在哪里,在56之间加上一句:cout<<"stu3name指向地址:"<<(int *)stu3.name<<"\t"<<"stu4name指向地址:"<<(int *)stu4.name<<endl;
输出(您可以不要直接cout<<"stu3name指向地址:"<<&stu3.name<<"\t"<<"stu4name指向地址:"<<&stu4.name<<endl;这样来访问,这是获取该指针在堆栈中的地址,而不是内容在堆中存储的地址)

要解决这个问题。。看样子只有重写拷贝构造函数了(下面是重构拷贝构造函数)

student::student(const student& tempstu)

{

int len=strlen(tempstu.name);

name=new char[len+1];

strcpy(name,tempstu.name);

}

以为一切问题解决,可是运行的时候
很明显这是在析构1的时候,即析构stu1的时候,发现第7stu5=stu1;这只是一个赋值过程,因为stu5对象在第6句就构造了,赋值的过程的话,即依然是stu5.name=stu1.name,然后问题原因道理同上。这就是所谓的浅复制的过程,这也是浅复制容易导致的问题(大家可以去研究浅复制和深复制)
至于结构中的最后 的剩余个数为什么编程-2了,(其实这个例子模仿c++ primer),主要是因为位置4调用了fun(stu2);-这个调用,传递了一个实参为stu2的类对象,在传递过程类似
student  funs=stu2;这个funs对象在fun方法返回时会销毁,销毁就会调用析构函数num--,而且在第5位置处,是通过student stu4=stu3这种拷贝构造函数来实例化stu4,在重写的拷贝构造函数中,我们并没有让num++,而析构他的时候却有num--了,这就是为什么最后num不会回归至初始0,而是-2

转载于:https://www.cnblogs.com/yinhaichao/archive/2013/04/25/3042303.html

你可能感兴趣的文章
[Android学习系列16]Android把php输出的json加载到listview
查看>>
20145205 《信息安全系统设计基础》第14周学习总结
查看>>
6)添加一个窗口的图标
查看>>
POJ - 1422 Air Raid 二分图最大匹配
查看>>
Road Map
查看>>
正则替换中的一个Bug
查看>>
HI3531uboot开机画面 分类: arm-linux-Ubunt...
查看>>
制作U盘启动CDLinux 分类: 生活百科 ...
查看>>
strcpy函数里的小九九
查看>>
搭建ssm过程中遇到的问题集
查看>>
OpenLayers绘制图形
查看>>
tp5集合h5 wap和公众号支付
查看>>
Flutter学习笔记(一)
查看>>
iOS10 国行iPhone联网权限问题处理
查看>>
洛谷 P1991 无线通讯网
查看>>
Codeforces Round #178 (Div. 2) B. Shaass and Bookshelf 【动态规划】0-1背包
查看>>
SparkStreaming 源码分析
查看>>
【算法】—— 随机音乐的播放算法
查看>>
mysql asyn 示例
查看>>
数据库第1,2,3范式学习
查看>>