大学学了越来越多的算法技术,但却不能忽略本源,编程语言是一切的基础,回过头来看依旧存在许多知识漏洞。返濮方能归真!!
前几天翻看别人的面经,发现了一个很有意思的问题,用new开出来的空间用free释放会怎样,借此机会,复习一下析构函数,并写了一个测试案例,来深度分析。
#include <iostream>
#include <string.h>
//#include <bits/stdc++.h> //c++万能头
using namespace std;
class test
{
private:
public:
int num;
char* str1;
char* str2;
test();
~test();
};
test::test()
{
cout << "construct" << endl;
num = 10;
str1 =(char*)malloc(5);
strcpy(str1, "abcd");
str2=new char[5];
strcpy(str2, "abcd");
}
test::~test()
{
cout << "destroy" << endl;
//free(str1);
//delete []str2;
}
int main()
{
test* a = new test();
test* b = new test();
cout << a->str2 << endl;
cout << b->str2 << endl;
cout << a->num << endl;
cout << b->num << endl;
delete a;
delete b;
cout << a->str2 << endl;
cout << b->str2 << endl;
cout << a->num << endl;
cout << b->num << endl;
}
运行结果如下
可以发现两个对象在走完析构后,在栈区的变量num是完成了释放,而由我们自己开在堆区的字符串指针变量却没有释放,因此如果类中有自己动态开的空间,系统不会帮你释放,一定要在析构函数中自己释放。这样可以避免内存泄漏。
1、成员变量如果是指针。那么程序需要分配的内存是存储指针占用的内存(32位程序是4个字节)和指针指向的内存。其中指针占用的内存是有编译器管理的,而指针指向的内存是你自己管理的。也就是,这个指针占用的内存(4个字节)就会自动在析构函数里自动释放。但是指针指向的部分内存默认析构函数是不会帮你释放的,因为编译器也不知道你这个指针指向的是不是你自己分配的内存,也不知道你将来还会不会用这段内存。
2、当程序/进程执行完,程序占用的所有内存都会被操作系统释放。即使没有显示的delete
。
接下来对析构函数进行修改,将对象b改由用free释放。
#include <iostream>
#include <string.h>
//#include <bits/stdc++.h> //c++万能头
using namespace std;
class test
{
private:
public:
int num;
char* str1;
test();
~test();
};
test::test()
{
cout << "construct" << endl;
num = 10;
str1 =(char*)malloc(5);
strcpy(str1, "abcd");
}
test::~test()
{
cout << "destroy" << endl;
free(str1);
//delete[]str2;
}
int main()
{
test* a = new test();
test* b = new test();
cout << a->str1 << endl;
cout << b->str1 << endl;
cout << a->num << endl;
cout << b->num << endl;
delete a;
free(b);
cout << a->str1 << endl;
cout << b->str1 << endl;
cout << a->num << endl;
cout << b->num << endl;
//system("cls");
return 0;
}
运行结果
可以看到对象b没有调用析构函数,num和字符串指针都没有被释放,也许有些编译器比较智能,能检查出问题,自动释放,有些情况,编译器不会报错,一些在栈区的变量例如num也许会被释放
但你动态开的绝不可能,因为根本没走析构函数。
一句话总结free去释放new开出来的对象不会走析构函数,对象里有些动态开的空间释放不了就会导致内存泄漏。
相反我们可以大胆的推测如果用malloc给对象开空间,再用delete释放,是不会走构造函数的,所有对象绝对不能用malloc开空间。