C++ 中内存分区总结

2023-11-12

背景

C++ 中最基本的存储单位是字节,C++ 中所有的数据都是由对象组成的,每一个对象都包含了一个或多个内存位置。
C++ 中有多种不同类型的内存区域,不同区域存放不同的数据,赋予数据不同的生命周期。
程序在执行时将供用户使用内存大致划分为以下区域:常量数据区、全局/静态数据区、栈区、堆区、自由存储、代码区。

常量数据区

①.常量数据区主要用于存储字符串常量或者其他在编译期就已经知道的数据。

②.常量数据区中的数据在整个程序的生命周期中都有效。

③.常量数据区中的数据在程序结束后由操作系统进行释放。

④.常量数据区中的数据是只读的。

全局/静态数据区

①.全局/静态数据区主要用于存放全局变量和静态变量。
②.在程序启动时,全局/静态数据已经分配了存储空间。
③.全局/静态数据区中的数据在程序结束后由操作系统释放。
④.未初始化的静态变量会被程序自动初始化为 0,静态局部变量在程序执行到该对象的声明处时被首次初始化。

栈区

①.栈区用于存放函数的参数,局部变量、返回值等。
②.栈区的数据由编译器自动进行分配,在作用域内有效。
③.在超出变量作用域后,栈中数据由编译器自动释放。
④.栈内存分配运算内置于处理器的指令集,效率高、但是分配的内存容量有限。

自由存储

①.自由存储是动态内存区域,通过 new/delete 来分配和释放。
②.分配空间时,编译器根据指定类型自动分配空间大小,并调用构造函数进行初始化。
③.释放空间时,编译器会调用析构函数,并回收内存空间。
④.new 和 delete 必须配套使用。

堆区

①.堆是动态内存区域,通过 malloc/free 来分配和释放。
②.分配空间时,需要显示指定空间大小,不会调用构造函数。
③.释放空间时,编译器不会调用析构函数,只是释放内存空间。
④.malloc和 free 必须配套使用。

代码示例

#include "iostream"
#include <iomanip>

using namespace std;

constexpr int c_a = 10;
const int c_b = 2;

int g_a = 10;
static int s_g_b = 10;

int main()
{
	static int s_l_c = 0;

	int l_a = 2;
	const int l_c_b = 3;
	constexpr int l_c_c = 10;

	int * p_a = new int(10);
	void * p_b = malloc(sizeof(int));

	cout << "=========常量数据区======" << endl;
	cout <<setw(30) << left << "字符串常量 hello 地址:"<< static_cast<const void*>("hello") << endl;
	cout <<setw(30) << left << "常量表达式 c_a 地址:" << &c_a << endl;
	cout << setw(30) << left << "全局常量 c_b 地址:" << &c_b << endl;
	cout << "=========全局数据区======" << endl;
	cout << setw(30) << left << "全局变量 g_a 地址:" << &g_a << endl;
	cout << setw(30) << left << "静态全局变量 s_g_b 地址:" << &s_g_b << endl;
	cout << setw(30) << left << "静态局部变量 s_l_c 地址:" << &s_l_c << endl;
	cout << "=========栈区======" << endl;
	cout << setw(30) << left << "局部变量 l_a 地址:" << &l_a << endl;
	cout << setw(30) << left << "局部常量 l_c_b 地址:" << &l_c_b << endl;
	cout << setw(30) << left << "局部常量表达式 l_c_c 地址:" << &l_c_c << endl;
	cout << "=========自由存储======" << endl;
	cout << setw(30) << left << "指针 p_a 指向地址:" << p_a << endl;
	cout << "=========堆区======" << endl;
	cout << setw(30) << left << "指针 p_b 指向地址:" << p_b << endl;
	cout << "=========代码区======" << endl;
	cout << setw(30) << left << "main 函数地址:" << main << endl;

	system("pause");
    return 0;
}

运行结果如下:
在这里插入图片描述

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中内存分区总结 的相关文章

  • 在C语言中使用“void”

    我很困惑为什么我们需要通过void转换为 C 函数 int f void return 0 versus int f return 0 什么是正确的做法以及为什么 In C int f 是一种老式的声明 它说f需要固定但未指定数量和类型的参
  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • 在搜索 List 时,为什么 Enumerable.Any(Func predicate) 比带有 if 语句的 foreach 慢

    最近有件事引起了我的好奇心 Why is the Enumerable Any Func
  • 迭代变量并查找特定类型实例的技术

    我想迭代进程中内存中的变量 通过插件动态加载 并查找特定类型的实例 以前我可以找到特定类型 或内存中的所有类型 我可以创建类型的实例 我可以获取作为不同类型的字段包含的实例 但我无论如何都不知道只是 搜索 特定类型的实例 一种方法是使用 W
  • 如何在 Android NDK 中创建新的 NativeWindow 而无需 Android 操作系统源代码?

    我想编译一个 Android OpenGL 控制台应用程序 您可以直接从控制台启动 Android x86 运行 或者从 Android x86 GUI 内的 Android 终端应用程序运行 这个帖子 如何在 Android NDK 中创
  • 32 位应用程序的特征最大矩阵大小

    所以 我正在寻找Eigen http eigen tuxfamily org index php title Main Page当我尝试声明大于 10000x10000 的矩阵时 包崩溃 我需要声明一个像这样的矩阵 可靠地大约有 13000
  • Clang 编译器 (x86):80 位长双精度

    我正在尝试在 x86 Windows 平台上使用本机 80 位长双精度 海湾合作委员会选项 mlong double 80 https gcc gnu org onlinedocs gcc x86 Options html似乎不适用于 cl
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • 访问者和模板化虚拟方法

    在一个典型的实现中Visitor模式 该类必须考虑基类的所有变体 后代 在许多情况下 访问者中的相同方法内容应用于不同的方法 在这种情况下 模板化的虚拟方法是理想的选择 但目前这是不允许的 那么 模板化方法可以用来解析父类的虚方法吗 鉴于
  • 检查算术运算中的溢出情况[重复]

    这个问题在这里已经有答案了 可能的重复 检测 C C 中整数溢出的最佳方法 https stackoverflow com questions 199333 best way to detect integer overflow in c
  • Qt 创建布局并动态添加小部件到布局

    我正在尝试在 MainWindow 类中动态创建布局 我有四个框架 它们是用网格布局对象放置的 每个框架都包含一个自定义的 ClockWidget 我希望 ClockWidget 对象在调整主窗口大小时相应地调整大小 因此我需要将它们添加到
  • 在非活动联合成员上使用“std::addressof”是否定义明确[重复]

    这个问题在这里已经有答案了 下面的代码是尝试实现constexpr的版本offsetof在 C 11 中 它可以在 gcc 7 2 0 和 clang 5 0 0 中编译 这取决于申请std addressof工会非活跃成员的成员 这是明确
  • 如何在c#中的内部类中访问外部类的变量[重复]

    这个问题在这里已经有答案了 我有两个类 我需要声明两个类共有的变量 如果是嵌套类 我需要访问内部类中的外部类变量 请给我一个更好的方法来在 C 中做到这一点 示例代码 Class A int a Class B Need to access
  • 如何挤出平面 2D 网格并赋予其深度

    我有一组共面 连接的三角形 即二维网格 现在我需要将其在 z 轴上挤出几个单位 网格由一组顶点定义 渲染器通过与三角形数组匹配来理解这些顶点 网格示例 顶点 0 0 0 10 0 0 10 10 0 0 10 0 所以这里我们有一个二维正方
  • 运算符“==”不能应用于“int”和“string”类型的操作数

    我正在编写一个程序 我想到了一个数字 然后计算机猜测了它 我一边尝试一边测试它 但我不断收到不应该出现的错误 错误是主题标题 我使用 Int Parse 来转换我的字符串 但我不知道为什么会收到错误 我知道它说 不能与整数一起使用 但我在网
  • 使用 C# 从 DateTime 获取日期

    愚蠢的问题 给定日期时间中的日期 我知道它是星期二 例如我如何知道它的 tue 2 和 mon 1 等 Thanks 您正在寻找星期几 http msdn microsoft com en us library system datetim
  • WinRT 定时注销

    我正在开发一个 WinRT 应用程序 要求之一是应用程序应具有 定时注销 功能 这意味着在任何屏幕上 如果应用程序空闲了 10 分钟 应用程序应该注销并导航回主屏幕 显然 执行此操作的强力方法是在每个页面的每个网格上连接指针按下事件 并在触
  • 实例化 Microsoft.Office.Interop.Excel.Application 对象时出现错误:800700c1

    实例化 Microsoft Office Interop Excel Application 以从 winforms 应用程序生成 Excel 时 出现以下错误 这之前是有效的 但突然间它停止工作了 尽管代码和 Excel 版本没有变化 我
  • 是否可以在 C# 中强制接口实现为虚拟?

    我今天遇到了一个问题 试图重写尚未声明为虚拟的接口方法的实现 在这种情况下 我无法更改接口或基本实现 而必须尝试其他方法 但我想知道是否有一种方法可以强制类使用虚拟方法实现接口 Example interface IBuilder
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐