程序在运行的过程中是会被加载到内存中的,一个程序可能会执行可能会存在不同的功能块,所以不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程
C++的程序会在内存中分为四大块:
- 代码区:存放函数体的二进制代码,由操作系统进行管理的
- 全局区:存放全局变量和静态变量以及常量
- 栈区:由编译器自动分配释放, 存放函数的参数值,局部变量等
- 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
代码区
程序编译后是一个二进制的文件,这个二进制的文件便会放在代码区中。
代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令
全局区
- 全局变量和静态变量存放在此.
- 全局区还包含了常量区, 字符串常量和其他常量也存放在此.
- 该区域的数据在程序结束后由操作系统释放.
- C++中在程序运行前分为全局区和代码区
- 代码区特点是共享和只读
- 全局区中存放全局变量、静态变量、常量
- 常量区中存放 const修饰的全局常量 和 字符串常量,局部变量和局部常量是另外一个内存块的栈的。
大概了解下是怎么回事就行,可以定义不同的变量去观察它们所在的地址块是否连续在一起来判断。
栈区
局部变量,局部常量都会分配到栈区中。
在函数中,实参传递给形参的过程是先在栈区为形参开辟一块内存块,然后将实参的值写入形参所在的内存块。这就是为什么需要修改一个实参的数时需要传递指针或者引用(引用其实也是一个指针)。通过指针的地址再去改变相应的值。
一个函数执行完之后,都会把在这个函数中创建的形参(本质也是一个局部变量)或者局部变量进行退栈操作,也就是销毁。销毁后的值是没有意义的。所以不能在一个函数中返回一个形参的地址,这是相当危险的操作。
如下程序:
int* test() {
int i = 10; //在函数中创建的局部变量
return &i; // 返回i的地址
}
int main() {
int* p = test();
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
return 0;
}
结果:
10
1515108752
1515108752
结果只有第一次正确,这是因为编译器暂时保留了一会,等到第二次去取值时就错了。
堆区
那么,上面的问题中,我们要怎么在函数中创建变量,并且还不会在函数运行结束后就被销毁呢?
解决方案其实也很优雅,就是另外开辟一个堆区,将用户自己创建的变量都放到这个区中,然后用户自行删除或者等到程序结束时自动销毁。
主要是用new来开辟的内存空间的。
int* test() {
int* i = new int(10); // 在堆中开辟新的空间
return i; // 返回i
}
int main() {
int* p = test();
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
return 0;
}
结果:
10
10
10
总结:
堆区数据由程序员管理开辟和释放
堆区数据利用new关键字进行开辟内存
本文主要参考:黑马程序员匠心之作|C++教程从0到1入门编程
更多精彩内容请关注我微信公众号: