【C++核心】C++内存分区模型分析

简介: 这篇文章详细解释了C++程序执行时内存的四个区域:代码区、全局区、栈区和堆区,以及如何在这些区域中分配和释放内存。

C++程序在执行时,将内存大方向划分为4个区域

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

内存四区意义: 不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程

1. 程序运行前

​ 在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域

代码区: 存放 CPU 执行的机器指令,

1、代码区是 共享 的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
2、代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令

全局区: 全局变量和静态变量存放在此.

全局区还包含了常量区, 字符串常量和其他常量也存放在此。该区域的数据在程序结束后由操作系统释放.

示例:

#include<iostream>
using namespace std;

//全局变量
int g_a = 10;
int g_b = 10;

//全局常量
const int c_g_a = 10;
const int c_g_b = 10;

int main() {
   

    //局部变量
    int a = 10;
    int b = 10;

    //打印地址
    cout << "局部变量a地址为: " << &a << endl;
    cout << "局部变量b地址为: " << &b << endl;

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

    //静态变量
    static int s_a = 10;
    static int s_b = 10;

    cout << "静态变量s_a地址为: " << &s_a << endl;
    cout << "静态变量s_b地址为: " << &s_b << endl;

    cout << "字符串常量地址为: " << &"hello world" << endl;
    cout << "字符串常量地址为: " << &"hello world1" << endl;

    cout << "全局常量c_g_a地址为: " << &c_g_a << endl;
    cout << "全局常量c_g_b地址为: " << &c_g_b << endl;

    const int c_l_a = 10;
    const int c_l_b = 10;
    cout << "局部常量c_l_a地址为: " << &c_l_a << endl;
    cout << "局部常量c_l_b地址为: " << &c_l_b << endl;

    return 0;
}

执行结果为:

局部变量a地址为: 0x309764408
局部变量b地址为: 0x309764404
全局变量g_a地址为: 0x1029720c0
全局变量g_b地址为: 0x1029720c4
静态变量s_a地址为: 0x1029720c8
静态变量s_b地址为: 0x1029720cc
字符串常量地址为: 0x10296deb7
字符串常量地址为: 0x10296dec3
全局常量c_g_a地址为: 0x10296df4c
全局常量c_g_b地址为: 0x10296df50
局部常量c_l_a地址为: 0x309764400
局部常量c_l_b地址为: 0x3097643fc

总结:

  • C++中在程序运行前分为全局区和代码区
  • 代码区特点是共享和只读
  • 全局区中存放全局变量、静态变量、常量
  • 常量区中存放 const修饰的全局常量 和 字符串常量

2. 程序运行后

栈区: 由编译器自动分配释放, 存放函数的参数值,局部变量等

注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

示例:

#include<iostream>
using namespace std;

int * func()
{
   
    int a = 10;
    return &a;
}

int main() {
   

    int *p = func();

    cout << *p << endl;
    cout << *p << endl;

    return 0;
}

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

示例:

#include<iostream>
using namespace std;

int* func()
{
   
    int* a = new int(10);
    return a;
}

int main() {
   
    int *p = func();

    cout << *p << endl;
    cout << *p << endl;

    return 0;
}

总结:

  • 堆区数据由程序员管理开辟和释放
  • 堆区数据利用new关键字进行开辟内存

3. new操作符

C++中利用new操作符在堆区开辟数据,堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符 delete

​ 语法:new 数据类型

​ 利用new创建的数据,会返回该数据对应的类型的指针

案例1: 基本语法

#include<iostream>
using namespace std;

int* func()
{
   
    int* a = new int(10);
    return a;
}

int main() {
   
    int *p = func();

    cout << *p << endl;
    cout << *p << endl;

    //利用delete释放堆区数据
    delete p;

    //cout << *p << endl; //报错,释放的空间不可访问

    return 0;
}

案例2:开辟数组

#include<iostream>
using namespace std;

//堆区开辟数组
int main() {
   

    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 后加 []
    delete[] arr;

    return 0;
}
相关文章
|
4月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
158 26
|
9月前
|
存储 程序员 编译器
玩转C++内存管理:从新手到高手的必备指南
C++中的内存管理是编写高效、可靠程序的关键所在。C++不仅继承了C语言的内存管理方式,还增加了面向对象的内存分配机制,使得内存管理既有灵活性,也更加复杂。学习内存管理不仅有助于提升程序效率,还有助于理解计算机的工作原理和资源分配策略。
|
5月前
|
C语言 C++
c与c++的内存管理
再比如还有这样的分组: 这种分组是最正确的给出内存四个分区名字:栈区、堆区、全局区(俗话也叫静态变量区)、代码区(也叫代码段)(代码段又分很多种,比如常量区)当然也会看到别的定义如:两者都正确,记那个都选,我选择的是第一个。再比如还有这样的分组: 这种分组是最正确的答案分别是 C C C A A A A A D A B。
85 1
|
8月前
|
存储 Linux C语言
C++/C的内存管理
本文主要讲解C++/C中的程序区域划分与内存管理方式。首先介绍程序区域,包括栈(存储局部变量等,向下增长)、堆(动态内存分配,向上分配)、数据段(存储静态和全局变量)及代码段(存放可执行代码)。接着探讨C++内存管理,new/delete操作符相比C语言的malloc/free更强大,支持对象构造与析构。还深入解析了new/delete的实现原理、定位new表达式以及二者与malloc/free的区别。最后附上一句鸡汤激励大家行动缓解焦虑。
|
9月前
|
安全 C语言 C++
彻底摘明白 C++ 的动态内存分配原理
大家好,我是V哥。C++的动态内存分配允许程序在运行时请求和释放内存,主要通过`new`/`delete`(用于对象)及`malloc`/`calloc`/`realloc`/`free`(继承自C语言)实现。`new`分配并初始化对象内存,`delete`释放并调用析构函数;而`malloc`等函数仅处理裸内存,不涉及构造与析构。掌握这些可有效管理内存,避免泄漏和悬空指针问题。智能指针如`std::unique_ptr`和`std::shared_ptr`能自动管理内存,确保异常安全。关注威哥爱编程,了解更多全栈开发技巧。 先赞再看后评论,腰缠万贯财进门。
420 0
|
4月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
1284 0
|
4月前
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
371 0
|
4月前
|
存储 弹性计算 固态存储
阿里云服务器配置费用整理,支持一万人CPU内存、公网带宽和存储IO性能全解析
要支撑1万人在线流量,需选择阿里云企业级ECS服务器,如通用型g系列、高主频型hf系列或通用算力型u1实例,配置如16核64G及以上,搭配高带宽与SSD/ESSD云盘,费用约数千元每月。
357 0
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
880 0

热门文章

最新文章