C++入门基础篇:内存管理

本文是C++内存管理部分的学习分享 希望能够对你有所帮助~

那咱们废话不多说,直接开始吧!


1. 内存分布

1.1 引入

在开始之前,我们先来看一道题目:

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
 static int staticVar = 1;
 int localVar = 1;
 int num1[10] = { 1, 2, 3, 4 };
 char char2[] = "abcd";
 const char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof(int) * 4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
 free(ptr1);
 free(ptr3);
}

选择题:  

选项: A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)  

globalVar在哪里?____    

staticGlobalVar在哪里?____  

staticVar在哪里?____    

localVar在哪里?____  

num1 在哪里?____

char2在哪里?____    

*char2在哪里?___  

pChar3在哪里?____        

*pChar3在哪里?____  

ptr1在哪里?____          

*ptr1在哪里?____

思考的差不多了吗?答案揭晓:

变量/表达式存储区域
globalVarC(数据段)
staticGlobalVarC(数据段)
staticVarC(数据段)
localVarA(栈)
num1A(栈)
char2A(栈)
*char2A(栈)
pchar3A(栈)
*pchar3D(代码段/常量区)
ptr1A(栈)
*ptr1B(堆)

其实理解起来并不困难:

全局变量以及静态局部变量都在数据段上;

在函数中除了静态成员变量外,其他的变量都存在这个函数的栈帧中;(因此我们经常说出了函数成员变量也随之消失,本质上还是因为函数的栈帧内存归还给系统了)

只能读、多个进程共享的(这部分会在后续的学习中分享)且大小不变的数据都放在代码段中;

动态开辟的空间就是开在堆上的


1.2 内存区域划分

C/C++ 程序的内存区域划分如下:

内存区域描述
存储非静态局部变量、函数参数、返回值等,向下增长。
动态内存分配区域,向上增长。
数据段(静态区)存储全局变量、静态变量(如 staticGlobalVar 和 staticVar)。
代码段(常量区)存储可执行代码和只读常量(如字符串常量 "abcd")。
内存映射段用于文件映射、动态库加载等,用户可通过系统接口创建共享内存。

 


2. C语言动态内存管理

2.1 函数区别

  • malloc:分配指定字节的未初始化内存。

  • calloc:分配并清零初始化内存(参数为元素个数和大小)。

  • realloc:调整已分配内存的大小(可能迁移数据)。

2.2 注意事项

  • realloc 后,原指针 p2 可能失效,需直接释放 p3(见示例代码)。

void Test ()
{
 // 1.malloc/calloc/realloc的区别是什么?
 int* p2 = (int*)calloc(4, sizeof (int));
 int* p3 = (int*)realloc(p2, sizeof(int)*10);
 
 // 这里需要free(p2)吗?
 free(p3 );
}

3. C++内存管理(new/delete)

3.1 基本用法

int* ptr4 = new int;          // 分配一个 int  
int* ptr5 = new int(10);      // 分配并初始化为 10  
int* ptr6 = new int[3];       // 分配 3 个 int 的数组  

delete ptr4;                  // 释放单个对象  
delete[ ] ptr6;                // 释放数组  

3.2 自定义类型

  • new:调用构造函数。

  • delete:调用析构函数。

class A { /* ... */ };  
A* p2 = new A(1);  // 调用构造函数  
delete p2;         // 调用析构函数  

3.3 注意事项

看完上述对于内置类型以及自定类型的基本用法后,也许思维活跃的你就会想到:那如果我创建了多个自定义类型变量,但我就只用delete还能够达成我释放内存的目的吗?

class A
{
public:
	A(int a=1,int b=1)
	{
		_a = a;
		_b = b;
	}
    ~A()
    {
        cout<<"~A()"<<endl;
    }
private:
	int _a;
	int _b;
};
int main()
{
	A* p7 = new A[10];

	delete p7;

	return 0;
}

事实上,在我们运行代码后会发现系统报错了,为什么呢?

这里涉及到一个内存泄漏的问题:

首先当然就是只能释放一个对象的问题

当然,不只是这个

按理来说一个A类的对象大小根据内存对齐规则来定应该为8,那么我们这里开了10个对象就应该是开了80字节的空间,但我们检查一下会发现一个很神奇的现象

内存大小成了84个字节?!发生甚么事了?

其实另外的四个字节是用来存储对象个数的,拿这段代码来说是A[10]的这个10,并且这个数字存储的位置非常特殊,在指向的空间的前面

但是在调用delete的时候是直接从p7只想的位置释放的,那前面的这四个字接就泄露了......

但是为什么要保存这个成员个数呢?别急,答案将在下面第五点的实现原理部分揭晓~


4. operator new 与 operator delete函数

  • operator new:底层通过 malloc 实现,失败时抛出异常(malloc 返回 NULL)。

  • operator delete:底层通过 free 实现。

代码示例

void* operator new(size_t size) {  
    void* p = malloc(size);  
    if (p == nullptr) throw bad_alloc();  
    return p;  
}  

5. new/delete 的实现原理

5.1 内置类型

  • 与 malloc/free 类似,但支持异常机制。

5.2 自定义类型

  • new

    1. 调用 operator new 分配内存。

    2. 调用构造函数。

  • delete

    1. 调用析构函数。

    2. 调用 operator delete 释放内存。

因此,刚刚说到的10实际上是给delete[ ]用的,是要告诉它有多少个成员,这样它就知道需要调用多少次析构函数了,真是太~妙~了~

我们这时将写的显式析构函数注释掉:

class A
{
public:
	A(int a=1,int b=1)
	{
		_a = a;
		_b = b;
	}
    //~A()
    //{
        //cout<<"~A()"<<endl;
    //}
private:
	int _a;
	int _b;
};
int main()
{
	A* p7 = new A[10];

	delete p7;

	return 0;
}

再计算一次,发现新生成的内存大小会发现又变回80了

我也不卖关子了,这是因为类中没有了显式析构函数,构造函数中也没有额外申请资源(申请内存),那么系统就会认为此时的默认析构函数可调可不调,从而进行了优化,直接在p7开始指向的位置直接进行内存释放。

但不管怎么说,咱老老实实地将new与delete正确匹配着来用准没错!


6. malloc/free 与 new/delete 的区别

区别点malloc/freenew/delete
类型函数操作符
初始化不初始化new 可初始化
大小计算需手动计算自动计算(类型 + 数量)
返回值void*(需强转)类型指针(无需强转)
失败处理返回 NULL抛出异常
构造/析构不调用调用构造/析构函数


那么以上便是本次内存管理部分学习分享的全部内容了

十分感谢你能够看到这里~

如果感觉对你有帮助的话也请给我一键三连 这将会给我莫大的鼓舞!

后续我依旧会持续更新其他的内容 敬请期待

那么 就让我们

下次再见~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/966794.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DeepSeek开源多模态大模型Janus-Pro部署

DeepSeek多模态大模型部署 请自行根据电脑配置选择合适环境配置安装conda以及gitJanus 项目以及依赖安装运行cpu运行gpu运行 进入ui界面 请自行根据电脑配置选择合适 本人家用电脑为1060&#xff0c;因此部署的7B模型。配置高的可以考虑更大参数的模型。 环境配置 安装conda…

Chrome谷歌多开教程:实用方法与工具

不管是电子商务、技术测试、空投等不同专业领域&#xff0c;还是个人的工作和生活账号管理&#xff0c;使用不同的独立账户往往需要借助Chrome谷歌浏览器多开来提高效率。Chrome谷歌多开有哪些方法和工具&#xff1f;可以来参考以下实用内容。 一、Chrome谷歌多开方法与工具 1…

Hdoop之MapReduce的原理

简单版本 AppMaster: 整个Job任务的核心协调工具 MapTask: 主要用于Map任务的执行 ReduceTask: 主要用于Reduce任务的执行 一个任务提交Job --> AppMaster(项目经理)--> 根据切片的数量统计出需要多少个MapTask任务 --> 向ResourceManager(Yarn平台的老大)索要资源 --…

Palatir和它的AIP

Palantir是一家成立于2001年的美国大数据分析公司&#xff0c;由彼得Thiel创立&#xff0c;最初专注于反恐数据分析&#xff0c;后来逐步扩展到政府、金融、医疗等多个领域。其核心产品包括Gotham&#xff08;面向政府&#xff09;、Foundry&#xff08;面向商业&#xff09;、…

html 列动态布局

样式说明&#xff1a; /* 列动态布局&#xff0c;列之间以空格填充 */ li {display: flex;/* flex-direction: column; */justify-content: space-between; }

【C++高并发服务器WebServer】-13:多线程服务器开发

本文目录 一、多线程服务器开发二、TCP状态转换三、端口复用 一、多线程服务器开发 服务端代码如下。 #include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h>s…

活动预告 | 为 AI 新纪元做好准备:助力安全的业务转型

课程介绍 随着现代办公模式的不断演变和 AI 技术的迅速发展&#xff0c;企业在享受效率提升的同时&#xff0c;也面临着信息安全与数据保护的严峻挑战。在利用 AI 技术释放业务潜力的同时&#xff0c;如何确保数据质量与安全已成为企业发展的关键议题。 在本次线上课程中&…

鸿蒙harmony 手势密码

1.效果图 2.设置手势页面代码 /*** 手势密码设置页面*/ Entry Component struct SettingGesturePage {/*** PatternLock组件控制器*/private patternLockController: PatternLockController new PatternLockController()/*** 用来保存提示文本信息*/State message: string …

紧跟潮流,将 DeepSeek 集成到 VSCode

Visual Studio Code&#xff08;简称 VSCode&#xff09;是一款由微软开发的免费开源代码编辑器&#xff0c;自 2015 年发布以来&#xff0c;凭借其轻便、强大、且拥有丰富扩展生态的特点&#xff0c;迅速成为了全球开发者的首选工具。VSCode 支持多平台操作系统&#xff0c;包…

21.2.6 字体和边框

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 通过设置Rang.Font对象的几个成员就可以修改字体&#xff0c;设置Range.Borders就可以修改边框样式。 【例 21.6】【项目&#xff…

Windows下AMD显卡在本地运行大语言模型(deepseek-r1)

Windows下AMD显卡在本地运行大语言模型 本人电脑配置第一步先在官网确认自己的 AMD 显卡是否支持 ROCm下载Ollama安装程序模型下载位置更改下载 ROCmLibs先确认自己显卡的gfx型号下载解压 替换替换rocblas.dll替换library文件夹下的所有 重启Ollama下载模型运行效果 本人电脑配…

node.js + html + Sealos容器云 搭建简易多人实时聊天室demo 带源码

node.js html Sealos容器云 搭建简易多人实时聊天室demo 带源码 前言功能介绍&#xff08;demo演示&#xff09;sealos官网配置node.js 编写服务端代码前端ui 调用接口整体项目目录部署到服务器 前言 hello哦盆友们&#xff0c;这次我们来十几行代码做一个超简单的多人聊天…

MYSQL索引与视图

一、新建数据库 mysql> create database mydb15_indexstu; mysql> use mydb15_indexstu; 二、新建表 &#xff08;1&#xff09;学生表Student mysql> create table Student(-> Sno int primary key auto_increment,-> Sname varchar(30) not null unique,-…

win10向windows server服务器传输文件

win10向windows server服务器传输文件 遇到无法直接拖动文件进行传输时 解决方案&#xff1a; 1.点击显示选项 2.点击本地资源-详细信息 3.在窗口中选择你需要共享的磁盘 4.然后远程连接到Windows server服务器 5.登录Windows server服务器后&#xff0c;在此电脑下就能看…

【教程】docker升级镜像

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 自动升级 手动升级 无论哪种方式&#xff0c;最重要的是一定要通过-v参数做数据的持久化&#xff01; 自动升级 使用watchtower&#xff0c;可…

HTML应用指南:利用GET请求获取全国盒马门店位置信息

随着新零售业态的发展,门店位置信息的获取变得至关重要。作为新零售领域的先锋,盒马鲜生不仅在商业模式创新上持续领先,还积极构建广泛的门店网络,以支持其不断增长的用户群体。本篇文章,我们将继续探究GET请求的实际应用,我们使用Python的requests库通过GET请求,从盒马…

Linux内核数据结构之链表

对于链表的优缺点,我们对比数组可以说出一些,但在随机存储的情况下,我们会选择链表来处理,而我们使用双向链表时,经常会定义成如下形式: struct list_node {TYPE data;struct list_node *prev,*next; }; 相对应的链表结构如下: 对于该数据结构定义,存在一个局限,整个…

ctf网络安全题库 ctf网络安全大赛答案

此题解仅为部分题解&#xff0c;包括&#xff1a; 【RE】&#xff1a;①Reverse_Checkin ②SimplePE ③EzGame 【Web】①f12 ②ezrunner 【Crypto】①MD5 ②password ③看我回旋踢 ④摩丝 【Misc】①爆爆爆爆 ②凯撒大帝的三个秘密 ③你才是职业选手 一、 Re ① Reverse Chec…

250207-MacOS修改Ollama模型下载及运行的路径

在 macOS 上&#xff0c;Ollama 默认将模型存储在 ~/.ollama/models 目录。如果您希望更改模型的存储路径&#xff0c;可以通过设置环境变量 OLLAMA_MODELS 来实现。具体步骤如下&#xff1a; 选择新的模型存储目录&#xff1a;首先&#xff0c;确定您希望存储模型的目标目录路…

C# OpenCvSharp 部署MOWA:多合一图像扭曲模型

目录 说明 效果 项目 代码 下载 参考 C# OpenCvSharp 部署MOWA&#xff1a;多合一图像扭曲模型 说明 算法模型的paper名称是《MOWA: Multiple-in-One Image Warping Model》 ariv链接 https://arxiv.org/pdf/2404.10716 效果 Stitched Image 翻译成中文意思是&…