C++核心编程 1 程序的内存模型
1、内存分区模型
C++程序在执行时,将内存大方向划分为4个区域
代码区:存放函数体的二进制代码,由操作系统进行管理(写的所有代码都在代码区)
全局区:存放全局变量、静态变量以及常量
栈 区:由编译器自动分配释放,存放函数的参数值,局部变量等
堆 区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
内存四区的意义:不同区域的数据,赋予不同的生命周期,给我们更大的灵活编程
程序运行前:
在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域
代码区:
存放CPU执行的机器指令
代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令
全局区:
全局变量(main函数外面)和静态变量(在普通变量前加static)存放于此
全局区还包含了常量区,字符串常量 ("hello world") 和其他常量(const修饰的全局变量)也存放于此
该区域的数据在程序结束后由操作系统释放

总结:
C++中在程序运行前分为全局区和代码区
代码区特点是共享和只读
全局区中存放全局变量、静态变量、常量
常量区中存放const修饰的全局变量 和 字符串常量
程序运行后:
栈 区:
由编译器自动分配释放,存放函数的参数值,局部变量等
注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
#include<iostream>
using namespace std; //栈区数据注意事项 --- 不要返回局部变量的地址
//栈区的数据由编译器管理开辟和释放 int * func(int b) //形参数据也会放在栈区
{
b = 100;
cout << b << endl;
int a = 10; //局部变量 存放栈区,栈区的数据在函数执行完后自动释放
return &a; //返回局部变量的地址
} int main()
{
//接收函数的返回值
int * p = func(1); cout << *p << endl; //第一次可以打印出正确的数据 10 ,是因为编译器防止用户是误操作而做了一次保留
cout << *p << endl; //第二次这个数据就不再保留 打印出来的是乱码 因为局部变量a的内存已经被释放 system("pause");
return 0;
}
打印出来的结果:
堆 区:
由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
在C++中主要利用new在堆区开辟内存
实例:
#include<iostream>
using namespace std; int * func()
{
//利用new关键字 可以将数据开辟到堆区
//指针 本质也是局部变量,放在栈上。指针保存的数据是放在堆区
int * p = new int (10);
return p;
} int main()
{
int * p = func(); //接收函数的返回值 cout << *p << endl;
cout << *p << endl;
system("pause");
return 0;
}
打印结果:

new操作符
C++中利用new操作符在堆区开辟数据
堆区开辟的数据,由程序员手动开辟,手动释放,释放操作符delete
语法:new 数据类型
利用new创建的数据,会返回该数据对应的类型的指针
实例:1、基本语法
#include<iostream>
using namespace std; int * func()
{
//在堆区创建整型数据
//new返回的是 该数据类型的指针
int * p = new int (10);
return p;
} void test1() //new的基本语法
{
int * p = func();
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
//堆区数据由程序员管理开辟、释放,若想释放 利用关键字delete
delete p;
cout << *p << endl; //内存已经被释放,再次访问就是非法操作,会报错
}
int main()
{
//int * p = func(); //接收函数的返回值
test1(); system("pause");
return 0;
}
打印结果:
因为delete p 后,p已被释放,故第四次打印出错。
2、在堆区new数组
#include<iostream>
using namespace std; //2、在堆区利用new开辟数组
void test2()
{
//创建10个 整型数据的数组,在堆区
int * arr = new int[10]; //10代表数组有10个元素
for (int i = 0; i < 10; i++)
{
arr[i] = i + 100; //给10个元素赋值 100~109
}
for (int i = 0; i < 10; i++)
{
cout << arr[i] << endl;
}
//释放堆区数组
//释放数组的时候要加[]才可以
delete[] arr;
}
int main()
{
test2();
system("pause");
return 0;
}
打印结果:
C++核心编程 1 程序的内存模型的更多相关文章
- STM32F4编程手册学习2_内存模型
STM32F4编程手册学习2_内存模型 1. 内存映射 MCU将资源映射到一段固定的4GB可寻址内存上,如下图所示. 内存映射将内存分为几块区域,每一块区域都有一个定义的内存类型,一些区域还有一些附加 ...
- Java并发编程:JMM(Java内存模型)和volatile
1. 并发编程的3个概念 并发编程时,要想并发程序正确地执行,必须要保证原子性.可见性和有序性.只要有一个没有被保证,就有可能会导致程序运行不正确. 1.1. 原子性 原子性:即一个或多个操作要么全部 ...
- Java并发编程:JMM (Java内存模型) 以及与volatile关键字详解
目录 计算机系统的一致性 Java内存模型 内存模型的3个重要特征 原子性 可见性 有序性 指令重排序 volatile关键字 保证可见性和防止指令重排 不能保证原子性 计算机系统的一致性 在现代计算 ...
- JAVA并发编程的艺术 JMM内存模型
锁的升级和对比 java1.6为了减少获得锁和释放锁带来的性能消耗,引入了"偏向锁"和"轻量级锁". 偏向锁 偏向锁为了解决大部分情况下只有一个线程持有锁的情况 ...
- java并发编程(9)内存模型
JAVA内存模型 在多线程这一系列中,不去探究内存模型的底层 一.什么是内存模型,为什么需要它 在现代多核处理器中,每个处理器都有自己的缓存,定期的与主内存进行协调: 想要确保每个处理器在任意时刻知道 ...
- 【Windows核心编程】一个使用内存映射文件进行进程间通信的例子
进程间通信的方式有很多种,其底层原理使用的都是内存映射文件. 本文实现了Windows核心编程第五版475页上的demo,即使用内存映射文件来在进程间通信. 进程1 按钮[Create mappin ...
- [Windows核心编程]32bit程序在64bit操作系统下处理重定向细节[1]
这段时间,都在做Ring3层的普通32bit程序兼容64bit操作系统的代码修改,在此记录修改和学习心德.编程领域太广, 任何人经历有限,本人不是专家,所以我一贯原则是: 用到的时候,才去研究,在去记 ...
- Windows核心编程 第十七章 -内存映射文件(下)
17.3 使用内存映射文件 若要使用内存映射文件,必须执行下列操作步骤: 1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件. 2) 创建一个文件映射内核对象,告诉系统该 ...
- Windows核心编程 第十七章 -内存映射文件(上)
第1 7章 内存映射文件 对文件进行操作几乎是所有应用程序都必须进行的,并且这常常是人们争论的一个问题.应用程序究竟是应该打开文件,读取文件并关闭文件,还是打开文件,然后使用一种缓冲算法,从文件的各个 ...
随机推荐
- Map 综述(一):彻头彻尾理解 HashMap
转载自:https://blog.csdn.net/justloveyou_/article/details/62893086 摘要: HashMap是Map族中最为常用的一种,也是 Java Col ...
- webpack4 插件ProvidePlugin使用遇到的问题
根据博客https://www.cnblogs.com/geyouneihan/p/9769808.html学习webpack4中使用ProvidePlugin遇到了自定义js无法使用的问题,解决之后 ...
- ES6扩展——函数扩展之默认参数
1.函数的默认参数 //函数的默认参数 function add(a, b = 999){ console.log(a,b); //1 999 } add(1); 2. 函数的形参可以设置默认值,默认 ...
- Linux复习笔记-001-进程的管理
1.什么是进程? 进程是已经启动的可执行的程序运行实例. 程序是二进制文件,静态 ./bin/date/ /usr/sbin/ 进程:是程序运行的过程 2.Linux为1的进程? centos5或6为 ...
- Linux下Sed命令替换文件中的所有IP
命令: sed -ri 's/([0-9]{1,3}\.){3}[0-9]{1,3}/localhost/g' es_create_index.sh 如图:
- 区间DP的瞎扯淡
写在前面连个引言都不加就直接开1. 区间DP状态常见模板: f[i][j]常常表示第i个到第j个这个区间内达到题目要求,所需要的最小值(最大值) 如: 1. [石子合并](https://www.lu ...
- GO安装golang.org/x/net扩展库
在学习golang过程中,有部分示例代码使用到了非标准库golang.org/x/net/html相关的库函数,但是标准代码库中没有该库,因此需要自己安装: 我这里使用git下载源码进行的安装. 为了 ...
- 异步处理方式之信号(一):基础知识和signal函数说明
文章目录 1. 引言 2. 信号的概念 2.1 信号操作之忽略信号 2.2 信号操作之捕捉信号 2.3 信号操作之执行系统默认操作 2.4 常见的信号 3. 函数signal 3.1 signal函数 ...
- JS005. 拷贝引用数据类型Array使其指向不同堆的解决方案
一个很常见的语法问题,但专注实现需求时经常会忘记去避免,导致最终问题的出现,再花时间排查.为此专门整理一篇解决方法的博客,也加强一下自己的记忆. TAG: JSON.parse() JSON.stri ...
- Swagger-初见
目录 Swagger简介 SpringBoot集成Swagger 配置Swagger 配置扫描接口 配置Swagger开关 配置API分组 实体配置 常用注解 Swagger简介 前后端分离 前端 - ...