C++何时需要自定义析构函数呢?
2015-01-24 17:51
239 查看
对象销毁时
如果我们自己没有写析构方法,编译器会帮我们写一个然后调用。
那么问题来了,既然我不写,编译器会帮我写,那我干嘛要写???
有木有什么情况必须我自己写的????
处理内存的时候,也就是把之前retain的对象
都release一次
运行结果如下:
从运行结果可以知道创建的日期对象并没有销毁,所以有内存泄漏!肿么办?
员工销毁,员工的析构被调用。但是内存也泄漏。。。。为什么泄漏了?因为出了mian函数,员工对象销毁,两个成员变量name和日期指针birthday在员工销毁的时候弹栈了,但是birthday指针指向的堆内存并没有销毁。所以应该在指针销毁之前释放指针指向的内存空间。那么应该在哪里释放?员工对象在销毁的时候一定调用析构函数,所以在析构方法里对指针birthday进行delete,先把堆里开辟的内存空间清除掉,然后这个员工对象再销毁,所有内存才没有问题。
重写员工的析构函数如下:
再次运行结果如下:
总结:析构函数,如果我们自己不写,编译器会帮我们写(编译器自己写的析构里面什么都不干)。什么时候必须要我们自己写?如果本类中一个成员变量是别的对象的指针,而且这个指针不是传进来的地址而是这个指针指向的对象,是在本类中(如果是栈里的定位分配,也不用考虑内存)在堆中开辟的空间创建的。并且该指针没有进行过delete操作,那么久需要在析构方法中进行delete操作,此时我们就必须自己写析构函数
。
注意: delete一个没有指向的指针会报错
全局区的对象在程序一开始就创建,程序结束才会销毁。栈区的对象在调用函数(代码块,如for循环里面)的时候才会创建,出了函数就会销毁。 在堆中开辟空间创建的对象必须我们自己手动delete。
运行结果:
如果我们自己没有写析构方法,编译器会帮我们写一个然后调用。
那么问题来了,既然我不写,编译器会帮我写,那我干嘛要写???
有木有什么情况必须我自己写的????
处理内存的时候,也就是把之前retain的对象
都release一次
<span style="font-size:18px;">#include <iostream> using namespace std; //日期类 class Date{ int year,month,day; public: //构造方法 初始化列表 Date(int y,int m,int d):year(y),month(m),day(d){ cout << "创建日期类对象都会默认被动地调用一次构造方法" << endl; } //对象销毁时 如果我们自己没有写析构方法,编译器会帮我们写一个然后调用 #pragma 那么问题来了,既然我不写,编译器会帮我写,那我干嘛要写???有木有什么情况必须我自己写的????处理内存的时候,也就是把之前retain的对象 都release一次 ~Date(){ cout << "日期对象销毁都会默认被动地调用一次析构方法 ~Date()" << endl; } }; //员工类 class Employee{ string name; Date *birthday;//声明一个指针 在构造方法里面让它指向一个对象 public: //构造方法 Employee (string name):name(name){ birthday = new Date(1989,8,8);//这里会调用日期的构造方法 cout << "调用了员工类的构造方法" << endl; } //析构方法 ~Employee(){ cout << "员工对象销毁了" << endl; } }; //主函数 int main(){ Employee em("假如我是张三"); return 0; }</span>
运行结果如下:
<span style="font-size:18px;">创建日期类对象都会默认被动地调用一次构造方法 调用了员工类的构造方法 员工对象销毁了 Program ended with exit code: 0</span>
从运行结果可以知道创建的日期对象并没有销毁,所以有内存泄漏!肿么办?
员工销毁,员工的析构被调用。但是内存也泄漏。。。。为什么泄漏了?因为出了mian函数,员工对象销毁,两个成员变量name和日期指针birthday在员工销毁的时候弹栈了,但是birthday指针指向的堆内存并没有销毁。所以应该在指针销毁之前释放指针指向的内存空间。那么应该在哪里释放?员工对象在销毁的时候一定调用析构函数,所以在析构方法里对指针birthday进行delete,先把堆里开辟的内存空间清除掉,然后这个员工对象再销毁,所有内存才没有问题。
重写员工的析构函数如下:
//析构方法 ~Employee(){ delete birthday;//清除指针指向的内存空间 cout << "员工对象销毁了" << endl; }
再次运行结果如下:
创建日期类对象都会默认被动地调用一次构造方法 调用了员工类的构造方法 日期对象销毁都会默认被动地调用一次析构方法 ~Date() 员工对象销毁了 Program ended with exit code: 0
总结:析构函数,如果我们自己不写,编译器会帮我们写(编译器自己写的析构里面什么都不干)。什么时候必须要我们自己写?如果本类中一个成员变量是别的对象的指针,而且这个指针不是传进来的地址而是这个指针指向的对象,是在本类中(如果是栈里的定位分配,也不用考虑内存)在堆中开辟的空间创建的。并且该指针没有进行过delete操作,那么久需要在析构方法中进行delete操作,此时我们就必须自己写析构函数
。
注意: delete一个没有指向的指针会报错
全局区的对象在程序一开始就创建,程序结束才会销毁。栈区的对象在调用函数(代码块,如for循环里面)的时候才会创建,出了函数就会销毁。 在堆中开辟空间创建的对象必须我们自己手动delete。
<pre name="code" class="cpp"><pre name="code" class="cpp">//主函数 int main(){ Employee em("假如我是张三"); cout << "===== 1 栈里的对象 ======" << endl; for (int i = 0; i< 3; i++) { Date d(2015,1,23); } cout << "===== 2 ======" << endl; { Date d2(2015,1,2); Date d3(2015,1,3); Date d4(2015,1,5); cout << "===== 3 ===="<< endl; } cout << "=== 4 ====" << endl; { //这个代码块里会调用几次构造方法??0次 因为这里只是创建指针并没有创建开辟空间对象 Date *d5; Date *d6; Date *d7; } cout << "=== 5 ====" << endl; return 0; }
运行结果:
<pre name="code" class="cpp">===== 1 栈里的对象 ====== 创建日期类对象都会默认被动地调用一次构造方法 日期对象销毁都会默认被动地调用一次析构方法 ~Date() 创建日期类对象都会默认被动地调用一次构造方法 日期对象销毁都会默认被动地调用一次析构方法 ~Date() 创建日期类对象都会默认被动地调用一次构造方法 日期对象销毁都会默认被动地调用一次析构方法 ~Date() ===== 2 ====== 创建日期类对象都会默认被动地调用一次构造方法 创建日期类对象都会默认被动地调用一次构造方法 创建日期类对象都会默认被动地调用一次构造方法 ===== 3 ==== 日期对象销毁都会默认被动地调用一次析构方法 ~Date() 日期对象销毁都会默认被动地调用一次析构方法 ~Date() 日期对象销毁都会默认被动地调用一次析构方法 ~Date() === 4 ==== === 5 ====
相关文章推荐
- c++ 使用动态内存分配的类需要显式复制构造函数,赋值构造函数,析构函数
- 何时需要自定义复制构造函数?
- (需要确认一点)C++ 析构函数和delete运算符
- C++将析构函数为啥需要定义成virtual
- C++ 操作符重载(3) 什么时候需要自定义赋值操作符
- 详谈C++何时需要定义赋值/复制构造函数
- C++什么时候析构函数需要声明为虚函数
- c++ 什么情况下需要将基类的析构函数声明为虚函数
- 指针学习3----何时需要自行定义析构函数
- 何时需要单元测试以及C++单元测试工具选择
- C++中析构函数需要定义成虚函数的原因
- 自定义内存池(C++需要掌握)
- C++--何时需要定义赋值/复制构造函数
- C++ 虚函数、多态、为什么需要虚拟析构函数
- C++三法则:如果需要析构函数,则一定需要拷贝构造函数和赋值操作符
- 何时需要自定义拷贝构造函数和赋值运算符及二者区别
- C++:什么情况下需要将析构函数定义为虚函数?
- [C/C++标准库]_[初级]_[使用算法库函数时需要注意自定义BinaryPredicate和UnaryPredicate]
- [C/C++标准库]_[初级]_[使用算法库函数时需要注意自定义BinaryPredicate和UnaryPredicate]
- C++关于析构函数和拷贝构造函数何时调用两个例子的理解