C++内存四大区域
Posted 捕获一只小肚皮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++内存四大区域相关的知识,希望对你有一定的参考价值。
文章目录
前言
c++在执行程序(
.exe
程序)时候会对内存进行划分区域,主要目的就是方便更加高效以及灵活
编程.那么,在此过程阶段,是怎样划分区域,以及各区域都是在发挥着什么作用呢? 下面博主就详细的给大家介绍介绍
所划分的内存区块有?
在执行C++程序时候,所划分出的内存区块主要有四个:
代码区:
存放着程序的二进制代码,由操作系统管理全局区:
存放全局变量,静态变量,以及常量(字符常量和const
修饰的全局
变量)栈区:
存放所有的局部变量,其空间分配释放由编译器管理,当函数结束,局部变量自动被释放堆区:
存放所有动态开辟的变量,其空间分配释放由程序员管理
其中在exe程序
执行前只有代码区和全局区,在执行时才具有栈区与堆区
代码区解析
在代码区里面存放的是
exe
二进制机器指令,它(代码区
)具有两个特性:
共享性:
即在内存里面只有一份此程序代码,而无论谁都可以使用并运行它. 好处是当被频繁使用时,节约更多空间只读性:
即不允许被修改,这个很好理解.比如我们玩的王者游戏,官方设定一套皮肤100元,而当你下载此游戏并运行时候,有人给你修改了,变成一套皮肤1000元,你干吗?
全局区解析
全局区存的是全局变量,静态变量,以及常量,下面博主便演示下:
1 全局变量的地址
我们先定义几个全局变量,然后进行输出:
#include <iostream>
using namespace std;
int ga = 10; //g是global(全局)的意思
int gb = 20;
int gc = 20;
int main()
{
cout<<"全局变量ga的地址是"<<&ga<<endl;
cout<<"全局变量gb的地址是"<<&gb<<endl;
cout<<"全局变量gc的地址是"<<&gc<<endl;
return 0;
}
我们可以清晰的发现全局变量的地址都是很接近的.
2 静态变量的地址
我们定义几个静态变量,然后输出地址:
#include <iostream>
using namespace std;
int ga = 10; //g是global(全局)的意思
int gb = 20;
int gc = 20;
int main()
{
static int sa = 10;
static int sb = 20;
static int sc = 20;
cout << "全局变量ga的地址是" << &ga << endl;
cout << "全局变量gb的地址是" << &gb << endl;
cout << "全局变量gc的地址是" << &gc << endl;
cout << "静态变量sa的地址是" << &sa << endl;
cout << "静态变量sb的地址是" << &sb << endl;
cout << "静态变量sc的地址是" << &sc << endl;
return 0;
}
我们发现静态变量与全局变量的地址都是非常接近的,原因就是他们都存在全局区域
3 常量(字符常量及const全局常量)
一样的道理,首先创建常量,然后输出地址
#include <iostream>
using namespace std;
int ga = 10; //g是global(全局)的意思
int gb = 20;
int gc = 20;
const int cga = 10; //c是const
const int cgb = 10;
const int cgc = 10;
int main()
{
static int sa = 10;
static int sb = 20;
static int sc = 20;
cout << "全局变量ga的地址是" << &ga << endl;
cout << "全局变量gb的地址是" << &gb << endl;
cout << "全局变量gc的地址是" << &gc << endl;
cout << endl;
cout << "静态变量sa的地址是" << &sa << endl;
cout << "静态变量sb的地址是" << &sb << endl;
cout << "静态变量sc的地址是" << &sc << endl;
cout << endl;
cout << "字符常量1的地址是" << &"123"<<endl;
cout << "字符常量1的地址是" << &"124"<<endl;
cout << "字符常量1的地址是" << &"125"<<endl;
cout << endl;
cout << "const修饰的全局变量cga地址是" << &cga<<endl;
cout << "const修饰的全局变量cgb地址是" << &cgb<<endl;
cout << "const修饰的全局变量cgc地址是" << &cgc<<endl;
return 0;
}
我们仍然可以清晰的看到全局变量的地址都是在一定的区域段的(不要说相同段只有005B哦,这是16进制,换算成10进制,这个区段很大的)
栈区解析
栈区存放的是局部变量,现在我们用一些全局变量和局部变量进行比较
1 普通局部变量
#include <iostream>
using namespace std;
int ga = 10; //g是global(全局)的意思
int gb = 20;
int gc = 20;
int main()
{
int la = 10; //l是local(局部的意思)
int lb = 20;
int lc = 20;
cout << "全局变量ga的地址是" << &ga << endl;
cout << "全局变量gb的地址是" << &gb << endl;
cout << "全局变量gc的地址是" << &gc << endl;
cout << endl;
cout << "局部变量la的地址是" << &la << endl;
cout << "局部变量lb的地址是" << &lb << endl;
cout << "局部变量lc的地址是" << &lc << endl;
return 0;
}
可以发现局部变量前面区段的地址和全局变量差距特别大,这就很好的说明了全局区
和栈区
是两个不同区域
2 const修饰局部变量
我们用全局变量,全局const,局部变量,局部const进行对比
#include <iostream>
using namespace std;
int ga = 10; //g是global(全局)的意思
int gb = 20;
int gc = 20;
const int cga = 10; //c是const
const int cgb = 10;
const int cgc = 10;
int main()
{
int a = 10;
int b = 10;
int c = 10;
const int ca = 10;
const int cb = 20;
const int cc = 30;
cout << "全局变量ga的地址是" << &ga << endl;
cout << "全局变量gb的地址是" << &gb << endl;
cout << "全局变量gc的地址是" << &gc << endl;
cout << endl;
cout << "const修饰的全局变量cga地址是(全局常量)" << &cga << endl;
cout << "const修饰的全局变量cgb地址是(全局常量)" << &cgb << endl;
cout << "const修饰的全局变量cgc地址是(全局常量)" << &cgc << endl;
cout << endl;
cout << "局部变量a的地址是" << &a << endl;
cout << "局部变量b的地址是" << &b << endl;
cout << "局部变量c的地址是" << &c << endl;
cout << endl;
cout << "const修饰的局部变量ca的地址是(局部常量)" << &ca << endl;
cout << "const修饰的局部变量cb的地址是(局部常量)" << &cb << endl;
cout << "const修饰的局部变量cc的地址是(局部常量)" << &cc << endl;
return 0;
}
可以发现全局const常量和局部const常量他们的所属区是不一样的,局部const常量是所属于栈区.
3 栈区注意事项
栈区里面的变量不可返回地址,因为在func函数结束时候a的空间就被释放了,里面存的值就没有了,不信我们看下面:
#include <iostream>
using namespace std;
int* func()
{
int a = 10;
return &a;
}
int main()
{
int* p = func();
cout<<"*p的值是"<<endl;
return 0;
}
咦???,博主被打脸了哎,怎么还是可以访问到值呢?并且是正确的10
真的是这样吗?我们再调用几次试试?
发现是不是只有第一次调用才是正确的?其实之所以第一次调用对了,是因为编译器(VS2019)害怕你误用,特地给你保留了一次结果,哎~~,编译器为了我们这些憨憨可真是操碎了心.
堆区解析
堆区的开辟释放由程序员自己执行,开辟一般用
new
,释放一般用delete
#include <iostream>
using namespace std;
int* func()
{
int* p = new int(10); //看不懂这里的,下面有介绍new用法
return p;
}
int main()
{
int* p = func();
cout<<"func的值是"<<*p<<endl;
cout<<"func的值是"<<*p<<endl;
cout<<"func的值是"<<*p<<endl;
delete p;
return 0;
}
我们发现堆区就完全不受影响,其值仍然是堆区的值10
new的用法
1 开辟单个堆区元素
语法:
- 开辟:
type* name = new type(content);
type是元素类型,content是元素内容,name是变量名- 释放:
delete name
#include <iostream>
using namespace std;
int main()
{
int* p1 = new int(10); //开辟整型元素,存10进去
float* p2 = new float(20.12); //开辟单精度浮点,存20.12进去
char* p3 = new char('w'); //开辟字符元素,存'w'进去
cout << "整型元素的值是" << *p1 <<endl;
cout << "浮点元素的值是" << *p2 <<endl;
cout << "字符元素的值是" << *p3 <<endl;
delete p1;
delete p2;
delete p3;
return 0;
}
2 开辟数组
语法:
type* name = new type[size];
name是变量名,type是类型,size是数组空间数量- 释放:
delete []name
必须有一个[ ]哦~~~
#include <iostream>
using namespace std;
int main()
{
int* p1 = new int[10]; //开辟整型数组,10个元素
char* p2 = new char[10]; //开辟字符数组,10个元素
for (int i = 0; i < 10; i++) //整形数组赋值
p1[i] = i + 10;
for (int i = 0; i < 10; i++)//字符数组赋值
p2[i] = i + 65;
for (int i = 0; i < 10; i++) //打印
cout << p1[i] << ' ';
cout << endl;
for (int i = 0; i < 10; i++)
cout << p2[i] << ' ';
delete []p1;
delete []p2;
return 0;
}
以上是关于C++内存四大区域的主要内容,如果未能解决你的问题,请参考以下文章