当前位置: 首页 > news >正文

C++编程:进阶阶段—1内存模型

 1 程序的内存模型

C++在执行代码时,将内存分为4个区域,不同区域存放的数据,赋予不同的生命周期。

  • 代码区:存放函数体的二进制代码,由操作系统管理;
  • 全局区:存放全局变量、静态变量和常量;
  • 栈区:由编译器自动分配释放,存放函数的参数值、局部变量等;
  • 堆区:由程序员分配和释放,若程序员不释放,则程序结束时由操作系统回收。

1.1 内存四区---代码区

        代码区是程序运行前分的,在程序编译后运行前,分为代码区和全局区。代码区存放CPU执行的机器指令。

特点:

  • 共享:对于频繁被执行的程序,只需要在内存中有一份代码即可。
  • 只读:防止程序域外修改其中的指令。

1.2 内存四区---全局区

        存放全局变量、静态变量和常量。该区域的数据在程序结束后由操作系统释放

代码如下:

#include <iostream>
using namespace std;

//定义全局变量
int g_a=10;
int g_b=10;
const int c_g_a=0;
const int c_g_b=0;

int main()
{
    //全局区
    //存放全局变量
    //定义普通局部变量
    int a=10;
    int b=10;
    cout<<"局部变量a的地址为:"<<(long long)&a<<endl;
    cout<<"局部变量b的地址为:"<<(long long)&b<<endl;

    cout<<"全局变量g_a的地址为:"<<(long long)&g_a<<endl;
    cout<<"全局变量g_b的地址为:"<<(long long)&g_b<<endl;

    //定义静态变量
    static int s_a=0;
    static int s_b=0;
    cout<<"静态变量s_a的地址为:"<<(long long)&s_a<<endl;
    cout<<"静态变量s_b的地址为:"<<(long long)&s_b<<endl;

    //定义常量
    //字符串常量
    cout<<"字符串常量的地址为:"<<(long long)&"hello C++"<<endl;

    //const修饰的全局变量
    cout<<"全局常量c_g_a的地址为:"<<(long long)&c_g_a<<endl;
    cout<<"全局常量c_g_b的地址为:"<<(long long)&c_g_b<<endl;

    //const修饰的局部变量
    const int c_l_a=0;
    const int c_l_b=0;
    cout<<"局部常量c_l_a的地址为:"<<(long long)&c_l_a<<endl;
    cout<<"局部常量c_l_b的地址为:"<<(long long)&c_l_b<<endl;

    return 0;
}

输出如下:

全局变量的内存地址相近,与局部变量的地址相差明显远。

1.3 内存四区---栈区

        由编译器自动分配释放,存放函数的参数值、局部变量等,不要返回局部变量的地址(函数执行完之后会自动释放),栈区开辟的数据由编译器自动释放

代码如下:

#include <iostream>
using namespace std;

int* func()
{
    int a=0;//局部变量
    return &a;//返回局部变量的地址 报错(函数返回类型加一个 * 返回局部变量的地址就不会报错)
}

int main()
{
    //接收func函数的返回值
    int * p=func();
    cout <<*p<<endl;//报错
    return 0;
}

错误示例:

1.4 内存四区---堆区

        由程序员分配和释放,若程序员不释放,则程序结束时由操作系统回收。在C++中用new在堆区开辟内存

代码如下:

#include <iostream>
using namespace std;

int* func()
{
    //利用new将数据开辟到堆区
    int * p=new int(10);//用指针接收内存地址编号
    return p;
}

void func1()
{
    //在堆区开辟数组
    int * arr=new int[10];//用指针接收内存地址编号
    for(int i=0;i<10;i++)
    {
        arr[i]=i+100;
    }
    for(int i=0;i<10;i++)
    {
        cout<<arr[i]<<endl;
    }

    //释放数组
    delete[] arr;
}

int main()
{
    //接收func函数的返回值,接收的是在堆中开辟的地址,而不是局部变量在栈中的地址
    int * p=func();
    cout <<*p<<endl;
    cout <<*p<<endl;

    //手动释放内存
    delete p;
    cout<<*p<<endl;//报错 内存已被释放,再访问不会输出正确的值

    func1();
    return 0;
}

输出如下:

相关文章:

  • 【机器学习】应用梯度下降法训练线性回归算法模型
  • 玩转python: 深度解析Python高阶函数及推导式
  • 【UCB CS 61B SP24】Lecture 21: Data Structures 5: Priority Queues and Heaps 学习笔记
  • 如何在无图形化界面的服务器上下载百度网盘的超大文件(10GB以上)?
  • RefuseManualStart/Stop增强Linux系统安全性?详解systemd单元保护机制
  • 【时序预测】时间序列有哪些鲁棒的归一化方法
  • PMP项目管理—资源管理篇—5.管理团队
  • PySide(PyQT)的@Slot()、@pyqtSlot()装饰器的作用
  • 【区块链 + 绿色低碳】东方易电城市微电网智能平台 | FISCO BCOS 应用案例
  • 【Java---数据结构】链表 LinkedList
  • 物联网数据中台 数据采集器 边缘盒子三者之间应用思考点
  • Windows10系统构建本地安全私有化的个人知识库——采用DeepSeek+RAGFlow
  • Android中的Content Provider是什么以及它有哪些用途
  • 责任链模式:让请求在链条中流动
  • 数组扩展【ES6】
  • npm、Yarn 与 pnpm:选择最适合你的包管理工具
  • 汽车材料耐候性测试仪器-太阳光模拟器介绍
  • 9道Dubbo面试题
  • 爬虫Incapsula reese84加密案例:Etihad航空
  • 力扣记录(二)
  • 备案号是哪个网站/软文推广的优点
  • 昆山玉山网站建设/企业文化培训
  • 评论回复网站怎么做的/网站营销与推广
  • 做公司网站比较好的/政府免费培训 面点班
  • dw做网站有哪些用处/网络营销企业有哪些公司
  • 重庆豆花制作/手机seo百度点击软件