C++中构造函数和析构函数调用的时机
今天看书忽然对这个地方有点模糊,尤其是析构函数在调用默认的析构函数和用户自己覆写的析构函数的时候有点意识模糊呢。写段代码总结下
- #include <iostream>
- using namespace std;
- class Box
- {
- private:
- double length;
- public:
- Box(double lv=1.0):length(lv)//构造函数都没有返回值
- {
- cout << "constructor called" << endl;
- }
- ~Box()//重写的析构函数(重写是对继承类对基类的重新构造,这里表述不对)
- {
- cout << "destructor called" << endl;
- }
- };//万恶的分号,我老是忘掉
1、首先直接声明(定义)看下
//很多朋友指出我这里用声明不合适,在11楼作了一定解释,具体不在这里赘述,这里改为“定义”,谢谢大家的指正,但我也保留我自己的意见,所以没有把“声明”去掉
- int main()
- {
- Box box(2.3);
- }
这里看到一点java与c++的不同点,c++在声明的时候就创建了对象,java声明只是创建一个引用,并不会分配内存。言归正传,说明声明以后就调用了构造函数,然后退出的时候调用析构函数。
2、声明指针
- int main()
- {
- Box *box;
- }
可以看到,声明指针并不会调用构造函数,也不会分配内存空间。
3、用new创建
- int main()
- {
- Box *box=new Box(2.3);
- }
仅仅是调用构造函数创建了对象,分配了内存空间。但是没有调用析构函数,因为box指定的对象的内存是由new来创建分配的,编译器不能够自动调用析构函数将其删除。所以需要调用delete才可以。
4、用new创建对象,并delete掉
- int main()
- {
- Box *box=new Box();
- delete box;
- }
这次调用了析构函数。可以看出,此时的析构函数不是编译器自己调用的,是由我们的程序来主动调用的,所以以后需要注意。new了的需要手动释放内存空间
5、什么时候需要重写析构函数?
- class Message()
- {
- private:
- char *message;
- public:
- Message(const char* text="default message")
- {
- message = new char[strlen(text)+1];
- strcpy(message, text);
- }
- void showit()
- {
- cout << "message: " << message << endl;
- }
- ~Message()
- };
- Message::~Message()
- {
- cout << "destructor called" << endl;
- delete [] message;
- }
从例子可以看到,当你的构造函数中调用了new来创建对象的内存分配空间,则需要专门调用delete来释放内存,所以此时需要覆写析构函数,来专门的释放此内存空间
6、对象的形参传值问题:(话外题,仅作记录用)
先看代码及运行结果
- #include <iostream>
- using namespace std;
- class Box
- {
- private:
- double length;
- public:
- Box(double lv=1.0):length(lv)//构造函数都没有返回值
- {
- cout << "constructor called" << endl;
- }
- ~Box()
- {
- cout << "destructor called" << endl;
- }
- void showit()
- {
- cout << this->length << endl;
- }
- };
- void display(Box box)//关键注意这个地方。。。。。。。。。。。。。。。。。。。。。。。。。
- {
- box.showit();
- }
- int main()
- {
- Box box;
- display(box);
- }
运行结果
如果将上面的display代码改为
- void display(Box &box)//改为调用的是引用
- {
- box.showit();
- }
运行结果
可以明显的看到不加引用的时候会出现两个析构函数的调用。为什么呢?
直接传参,是形参传递,所以会另外创建一个对象来复制main函数里的对象box,所以在display调用完成时刻要调用析构函数来释放这个函数创建的形参对象的内存空间。但是如果是传递的引用,就只有一个参数对象了,所以只调用一个。
如果是平时的基本类型,你应该了解,直接把main里的box的值复制给形参box就是了,但是到了对象这里就有点复杂,如果是里面就是单纯的像上面的例子一样double类型等,其自带有复制函数就可以将各个成员值复制到形参对象里,但是如果里面有引用,比如char *pp = new char[100],那么复制的只是地址,两个对象公用一个地址,有可能就会造成错误。所以以后需要注意这一点,调用对象需要用引用哦。。。。。(要不你自己另写一个复制函数。)
C++中构造函数和析构函数调用的时机的更多相关文章
- C++类的继承中构造函数和析构函数调用顺序例子
/*当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止.简而言之,对象是由“底层向上”开始构造的.因为,构造函数 ...
- C++构造函数和析构函数调用虚函数时都不会使用动态联编
先看一个例子: #include <iostream> using namespace std; class A{ public: A() { show(); } virtual void ...
- C++单继承的构造函数和析构函数调用的顺序
1.继承构造函数调用顺序以及销毁的过程 先调用父类的构造函数,在调用子类的构造函数,析构函数调用相反.
- [第二章]c++学习笔记5(构造函数和析构函数调用时机)
示例函数 注:输出并不一定从main函数开始,如全局对象的初始化在main函数前执行,如构造函数中存在输出,则从构造函数的输出开始 此处6被类型转换构造函数的存在转换为临时对象赋值,而在这个过程结束后 ...
- C++ 构造函数或析构函数调用虚函数
构造函数和析构函数中的虚函数 在执行基类构造函数时,对象的派生类部分是未初始化的.实际上,此时对象还不是一个派生类对象. 为 了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化.在基类 ...
- 12.C++-构造函数与析构函数调用顺序,const成员函数,const对象
单个对象创建时,构造函数的调用顺序 1.首先判断该对象的类是否拥有父类,若有则先调用父类的构造函数 2.判断该对象的成员是否是其它类的成员,若是则调用成员变量的构造函数(调用顺序和声明顺序相同) 3. ...
- C++C++中构造函数与析构函数的调用顺序
http://blog.csdn.net/xw13106209/article/details/6899370 1.参考文献 参考1: C++继承中构造函数.析构函数调用顺序及虚函数的动态绑定 参考2 ...
- c++深/浅拷贝 && 构造函数析构函数调用顺序练习题
1.深/浅拷贝 编译器为我们提供的合成拷贝构造函数以及合成的拷贝赋值运算符都是浅拷贝.浅拷贝只是做简单的复制,如果在类的构造函数中new出了内存,浅拷贝只会简单的复制一份指向该内存的指针,而不会再开辟 ...
- C++中构造函数和析构函数的调用顺序
一般而言,析构函数调用的顺序和构造函数调用顺序相反,但是,对象的存储类别可以改变调用析构函数的顺序.举例说明: CreateAndDestroy类的定义 CreateAndDestroy类的成员函数的 ...
随机推荐
- jquery 里面的$(document).ready 和 DOMContentLoaded
DOMContentLoaded 事件是当页面的初始dom tree加载好了就会执行. 而不会去等待外部的css 渲染完成和 js执行完成,即下图中的DOM Tree阶段 DOMContentLoad ...
- python实用函数
dir([obj]) 显示对象属性, 无参数显示全局变量的名字 help([obj]) 显示对象的文档字符串 int(obj) 将一个对象转换为整数 len(obj) 返回对象的长度 range([[ ...
- Python设计模式——工厂方法模式(FactoryMethod)
需求:有一个学雷锋活动,有买米和扫地两个内容,参与的人有大学生和社区志愿者,他们各自的方法不一样. 如果用简单工厂模式实现: #encoding=utf-8 __author__ = 'kevinlu ...
- Drupal commerce 性能优化
从开始的时候打开一个页面需要超过9秒的时间到现在可以在3秒内打开,给自己带来了很多欣慰. 开始的时候是认为server性能不足,所以讲aliyun服务器从1核升级到了4核,但是发现升级之后和升级之前是 ...
- 基于Emgu CV 的手势识别实现PPT的控制放映
Emgu CV 简介 众所周知,Emgu CV是.NET平台下对OpenCV图像处理库的封装,也就是.NET版的OpenCV.开发者可以很方便的通过C#,VB等语言调用OpenCV函数 ...
- Asp.Net检查HTML是否闭合以及自动修复
1.htmlCheck类 using System; using System.Collections.Generic; using System.Text; using System.Collect ...
- ViewController 之间设置转场动画
AddOrEditViewController *addOrEdit = [[AddOrEditViewController alloc] init]; CATransition *transitio ...
- MongoDB应用详解
mongodb是一个用来存储管理数据的软件 他是一个 c/s 架构的软件,是一个网络类型的软件如果要是使用mongodb的话,首先需要开启mongodb的服务端,然后通过客户端软件去连接服务器 1.要 ...
- 使用PyInstaller打包Python程序
本文转载自: http://www.pycoding.com/2015/04/23/pyinstaller.html
- Python标准库与第三方库详解(转载)
转载地址: http://www.codeweblog.com/python%e6%a0%87%e5%87%86%e5%ba%93%e4%b8%8e%e7%ac%ac%e4%b8%89%e6%96%b ...