椋鸟C++笔记#5:C++内存管理

文章目录

      • C语言中的动态内存管理
      • C\+\+中的动态内存管理
        • 使用new/delete操作内置类型
        • 使用new/delete操作自定义类型
        • operator new(operator new[])与operator delete(operator delete[])函数
          • operator new函数
          • operator delete函数
          • operator new[]和operator delete[]
        • new与delete的实现原理
        • 定位new表达式(placement-new)
      • 检测内存泄露

萌新的学习笔记,写错了恳请斧正。

C语言中的动态内存管理

C语言中,我们使用malloccallocreallocfree来动态管理内存。

int main()
{int* p = (int*)malloc(sizeof(int));	//动态开辟free(p);int* q = (int*)calloc(4, sizeof(int));	//动态开辟并赋值int* r = (int*)realloc(q, 10 * sizeof(int));	//重新分配空间free(r);
}

C++中的动态内存管理

C++中有更简单方便的内存管理方式,那就是使用newdelete来管理内存。

使用new/delete操作内置类型

注意:如果使用new开辟空间就用delete删除,如果使用new[]开辟数组就用delete[]删除。

  1. 动态申请与删除一个内置类型变量的空间:

    int* pi = new int;
    int* pf = new float;
    int* pl = new long;
    int* pb = new bool;delete pi;
    delete pf;
    delete pl;
    delete pb;
    
  2. 动态申请与删除一个内置类型变量的空间并完成初始化:

    int* pi = new int(114514);
    int* pf = new float(3.14f);
    int* pl = new long(1145141919810);
    int* pb = new bool(true);delete pi;
    delete pf;
    delete pl;
    delete pb;
    
  3. 动态申请与删除内置类型变量数组的空间:

    int* pi = new int[5];
    int* pf = new float[5];
    int* pl = new long[5];
    int* pb = new bool[5];delete[] pi;
    delete[] pf;
    delete[] pl;
    delete[] pb;
    
  4. 动态申请与删除内置类型变量数组的空间并完成初始化:

    int* pi = new int[5]{1, 2, 3, 4, 5};
    float* pf = new float[5]{1.1f, 2.2f, 3.3f, 4.4f, 5.5f};
    long* pl = new long[5]{10, 20, 30, 40, 50};
    bool* pb = new bool[5]{true, false, true, false, true};delete[] pi;
    delete[] pf;
    delete[] pl;
    delete[] pb;
    
使用new/delete操作自定义类型

这与自定义类型区别主要在于:使用new/delete操作自定义类型时会自动调用自定义类型的构造/析构函数。

class A
{
public:A(int a = 0): m_a(a){cout << "A" << endl;}~A(){cout << "~A" << endl;}private:int m_a;
};int main()
{A* oA = new A;delete oA;A* oB = (A*)malloc(sizeof(A));free(oB);return 0;
}

该程序运行结果为:

A
~A
operator new(operator new[])与operator delete(operator delete[])函数

看到operator new和operator delete,很多人会以为这是new与delete的重载函数。

但是,operator new和operator delete不能理解为是new与delete的重载函数!

operator new与operator delete其实是系统提供的全局函数,而new和delete在底层其实就是调用了这两个函数来实现的。

以下给出的函数定义随编译器不同有所变化!

operator new函数
void* operator new(std::size_t size) 
{if (size == 0)	// 如果请求的大小为0,分配至少一个字节{size = 1;}while (true){void* p = std::malloc(size);  // 使用malloc分配内存if (p) {return p;  // 如果分配成功,返回指针}std::new_handler handler = std::get_new_handler();  // 获取当前的new_handlerif (!handler) {throw std::bad_alloc();  // 如果没有设置new_handler,抛出bad_alloc异常}handler();  // 调用new_handler}
}
operator delete函数
void operator delete(void* ptr) noexcept	//noexcept说明此函数不会抛出异常
{std::free(ptr);  // 使用free释放内存
}
operator new[]和operator delete[]

同样的,new[]和delete[]在底层调用的是operator new[]和operator delete[]函数。

void* operator new[](std::size_t size) 
{if (size == 0) {size = 1;}while (true) {void* p = std::malloc(size);if (p) {return p;}std::new_handler handler = std::get_new_handler();if (!handler) {throw std::bad_alloc();}handler();}
}void operator delete[](void* ptr) noexcept 
{std::free(ptr);
}
new与delete的实现原理

如果申请的是内置类型的空间,new和malloc、delete和free基本类似。

不同的是:

  1. new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间
  2. new在申请空间失败时会抛异常;malloc会返回NULL。

对于自定义类型:

  1. new的原理:
    • 调用 operator new 函数申请空间。
    • 执行构造函数。
  2. delete的原理:
    • 执行析构函数。
    • 调用 operator delete 函数释放空间。
  3. new[]的原理:
    • 调用 operator new[] 函数申请空间。
    • 分别执行构造函数。
    • 在这片空间前紧挨的位置申请4个字节用于保存N。
  4. delete[]的原理:
    • 往前读取4个字节,获得N。
    • N个元素分别执行析构函数。
    • 调用 operator delete[] 函数释放空间。
定位new表达式(placement-new)

我们可以直接通过指针显式的调用析构函数:

#include <iostream>using namespace std;class A
{
public:A(int a = 0): m_a(a){cout << "A()" << this << endl;}~A(){cout << "~A()" << this << endl;}private:int m_a;
};int main()
{A* p1 = new A;p1->~A();free(p1);return 0;
}

那我们能直接显式调用构造函数吗?答案是否定的。

但是我们可以使用定位new表达式

#include <iostream>using namespace std;class A
{
public:A(int a = 0): m_a(a){cout << "A()" << this << endl;}~A(){cout << "~A()" << this << endl;}private:int m_a;
};int main()
{A* p1 = (A*)malloc(sizeof(A));new (p1) A;	//在地址p1处执行类A的构造函数p1->~A();free(p1);return 0;
}

其结构就是new加上(这里放地址)加上类名

或者也可以同时初始化:

int main()
{A* p1 = (A*)malloc(sizeof(A));new (p1) A (10);	//在地址p1处执行类A的构造函数并初始化为10p1->~A();free(p1);return 0;
}

当然我们也能显示的调用operator new(operator new[])与operator delete(operator delete[])函数:

#include <iostream>using namespace std;class A
{
public:A(int a = 0): m_a(a){cout << "A()" << this << endl;}~A(){cout << "~A()" << this << endl;}private:int m_a;
};int main()
{A* p1 = (A*)malloc(sizeof(A));new (p1) A;p1->~A();free(p1);A* p2 = (A*)operator new(sizeof(A));new (p2) A(10);p2->~A();operator delete(p2);return 0;
}

检测内存泄露

在 Visual Stodio 中我们可以使用_CrtDumpMemoryLeaks()函数来检测内存泄露,如果发生内存泄露这个函数会在输出窗口给出提示。

#include <iostream>using namespace std;int main()
{int* p = new int;_CrtDumpMemoryLeaks();return 0;
}

执行这段代码,我们可以在来源为调试的输出看到如下内容:

Detected memory leaks!
Dumping objects ->
{81} normal block at 0x00000221287C7400, 4 bytes long.Data: <    > CD CD CD CD 
Object dump complete.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ref和out

学习ref和out的原因 它们可以解决在函数内部改变外部传入的内容&#xff0c;里面变了&#xff0c;外面也要改变。 static void ChangeValue(int value) {value 3; }static void ChangeArrayValue(int[] arr) {arr[0] 99; }static void ChangeArray(int[] arr) {//重新声明了…

linux centos consul1.15.2一键安装部署

consul原理、作用、安装相关内容 一、理论部分二、安装下载版本地址三、安装consul服务 一、理论部分 1、consul的原理 Consul的原理及作用可以归纳为以下几点&#xff1a; ①、基于Gossip协议的通信&#xff1a;Consul使用了基于Gossip协议的Serf实现来进行通信。 Gossip协议…

【DevOps】服务器硬件基础知识

目录 前言 1、处理器&#xff08;CPU&#xff09;&#xff1a;服务器的“大脑” 2、内存&#xff08;RAM&#xff09;&#xff1a;服务器的“工作台” 3、存储&#xff08;Storage&#xff09;&#xff1a;服务器的“仓库” 4、 网络接口&#xff08;NIC&#xff09;&…

【教学类-64-03】20240611色块眼力挑战(三)-2-10宫格色差10-50(10倍)适合中班幼儿园(星火讯飞)

背景需求&#xff1a; 【教学类-64-02】20240610色块眼力挑战&#xff08;二&#xff09;-2-25宫格&色差10-100&#xff08;10倍&#xff09;&#xff08;星火讯飞&#xff09;-CSDN博客文章浏览阅读360次&#xff0c;点赞17次&#xff0c;收藏13次。【教学类-64-02】2024…

Warning: `ReactDOMTestUtils.act` is deprecated in favor of `React.act`.

问题&#xff1a;在代码中使用jest进行单元测试时&#xff0c;报错如下&#xff1a; 解决思路&#xff1a; 根据报错提示出来的 react-dom/test-utils 进行全局搜索&#xff0c;发现没有该引用&#xff0c;故进入该代码块中分析。发现代码中引入testing-library/react &#…

算法设计与分析(5题Python版)

1、阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有N堆金币&#xff0c;第i堆金币的总重量和总价值分别是m,v。阿里巴巴有一个承重量为T的背包&#xff0c;但并不一定有办法将全部的金币都装进去。 他想装走尽可能多价值的金币&#xff0c;所有金币都可以随意分割&#xff0c;分…

【云岚到家】-day02-2-客户管理-认证授权

【云岚到家】-day02-2-客户管理-认证授权 第二章 客户管理1 认证模块1.1 需求分析1.2 小程序认证1.2.1 测试小程序认证1.2.1.1 参考官方流程1.2.1.2 申请小程序账号1.2.1.3 创建jzo2o-customer1.2.1.4 部署前端1.2.1.5 编译运行1.2.1.6 真机调试 2 阅读代码2.1 小程序认证流程2…

Qt——升级系列(Level Five):显示类控件、输入类控件、多元素控件、容器类控件、布局管理器

显示类控件 Label QLabel 可以⽤来显⽰⽂本和图⽚. 核⼼属性如下&#xff1a; 属性 说明 text QLabel 中的⽂本 textFormat ⽂本的格式. • Qt::PlainText 纯⽂本 • Qt::RichText 富⽂本(⽀持 html 标签) • Qt::MarkdownText markdown 格式 • Qt::AutoText 根…

Nginx配置详细解释:(4)高级配置

目录 1.网页的状态页 2.Nginx第三方模块(echo) 3.变量 4.自定义访问日志 5.Nginx压缩功能 6.https功能 7.自定义图标 Nginx除了一些基本配置外&#xff0c;还有一些高级配置&#xff0c;如网页的状态&#xff0c;第三方模块需要另外安装&#xff0c;支持变量&#xff0c…

【C语言初阶】循环语句

&#x1f31f;博主主页&#xff1a;我是一只海绵派大星 &#x1f4da;专栏分类&#xff1a;C语言 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、什么是循环语句 二、while语句 while语句中的break和continue break continue 三、for循环 break和continue在for循…

MAC安装idea教程

https://blog.csdn.net/qq_41810415/article/details/131649541 JDK安装 https://blog.csdn.net/dddebug/article/details/121713633 2、编辑.bash_profile文件 vim .bash_profile 进入编辑模式后 按 i 开始添加内容 结束编辑模式按 ESC 结束后保存输入 :wq! 不保存输入 :q! 检…

C++ - Clion安装Qt msvc2017版本教程,基础环境配置clion+ Qt5.12.12 msvc2017 + VS2019

背景&#xff1a;平时代码开发使用clion&#xff0c;但使用项目要制定mscv2017版本Qt。先装过mingw版本Qt无法运行&#xff0c;但msvc版本依赖装有Visual Studio&#xff0c;本地装的又是2019版。就出现了这个大坑&#xff0c;需要配置好clion Qt msvc2017 VS2019。 文章目录 …

【Git】Windows下使用可视化工具Sourcetree

参考&#xff1a;[最全面] SourceTree使用教程详解(连接远程仓库&#xff0c;克隆&#xff0c;拉取&#xff0c;提交&#xff0c;推送&#xff0c;新建/切换/合并分支&#xff0c;冲突解决&#xff0c;提交PR) 1.Git工具–sourcetree 之前文章介绍过Linux系统中的Git工具&…

Linux - 信号概念 信号产生

Linux - 信号概念 & 信号产生 信号概念信号产生软件信号killraiseabortalarm 硬件信号键盘产生信号硬件中断 信号概念 信号是进程之间事件异步通知的一种方式 在Linux命令行中&#xff0c;我们可以通过ctrl c来终止一个前台运行的进程&#xff0c;其实这就是一个发送信号的…

Mock数据

Mock 数据 引入依赖 <dependency><groupId>com.github.jsonzou</groupId><artifactId>jmockdata</artifactId><version>4.3.0</version></dependency>mock 数据 MockConfig mockConfig new MockConfig().sizeRange(1, 1);A.…

爱德华三坐标软件ACdmis.AC-dmis密码注册机

爱德华三坐标软件 AC-DMIS 是一款功能强大的三坐标测量软件&#xff0c;具有以下特点&#xff1a; • 支持多种测量模式&#xff1a;包括接触式测量、非接触式测量、复合式测量等&#xff0c;可以满足不同类型工件的测量需求。 • 高精度测量&#xff1a;采用先进的测量算法和…

助力高考,一组彩色的文字

1、获取文本内容 首先&#xff0c;获取每个<div>元素的文本内容&#xff0c;并清空其内部HTML&#xff08;innerHTML ""&#xff09;。 2、创建<span>元素 然后&#xff0c;它遍历文本的每个字符&#xff0c;为每个字符创建一个新的<span>元素…

通过python操作redis(windows)

注意在连接之前要确保 redis 服务已经安装。 更多的安装信息请查看&#xff1a;https://blog.csdn.net/sinat_20471177/article/details/132042779?spm1001.2014.3001.5501 redis 模块 Python 要使用 redis&#xff0c;需要先安装 redis 模块。如果要做数据导入/导出操作的…

34、matlab输入命令汇总

1、ans:最近计算的答案 代码示例1 12ans 3 代码示例2 Brand(7)B 列 1 至 60.7060 0.3171 0.1869 0.6797 0.5853 0.95930.0318 0.9502 0.4898 0.6551 0.2238 0.54720.2769 0.0344 0.4456 0.1626 0.7513 0.13860.0462 0.4387…

java程序100道01—20

1&#xff0e;用循环的嵌套&#xff0c;输出输出如下图形 * * * * * * * * * * * * * * * * * * * * * * * * * package Exercises.One_Hundred; ​ public class Demo01 {public static void main(String[] args) {for(int i1;i<5;i){for(int j1;j<2*i-1;j){Sys…