C C++最新【带你吃透C++】C+(2),做了三年C C++

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

我们来揭晓答案:

在这里插入图片描述

需要特别注意以下几个:

char char2[] = “abcd”;

char* pChar3 = “abcd”;

int* ptr1 = (int*)malloc(sizeof (int)*4);

char2是定义在栈区的数组,"abcd"存放与数组中

pChar3是定义在栈区的指针,存放的是定义在常量区"abcd"的地址,"abcd"通过指针pChar3由栈区指向常量区

同理: ptr1是定义在栈区的指针,存的是在堆区开辟的空间的地址

因此:

char2在栈区,*char2也在栈区

pChar3在栈区,对pChar3解引用操作(*pChar3)则指向了常量区(代码段)

ptr1在栈区,对 ptr1解引用操作(* ptr1)则指向了堆区

2.C语言中动态内存管理方式( malloc/calloc/realloc和free)

一、malloc

malloc函数的功能是开辟指定字节大小的内存空间,如果开辟成功就返回该空间的首地址,如果开辟失败就返回一个NULL。传参时只需传入需要开辟的字节个数。

二、calloc

calloc函数的功能也是开辟指定大小的内存空间,如果开辟成功就返回该空间的首地址,如果开辟失败就返回一个NULL。calloc函数传参时需要传入开辟的内存用于存放的元素个数和每个元素的大小。calloc函数开辟好内存后会将空间内容中的每一个字节都初始化为0。

三、realloc

realloc函数可以调整已经开辟好的动态内存的大小,第一个参数是需要调整大小的动态内存的首地址,第二个参数是动态内存调整后的新大小。realloc函数与上面两个函数一样,如果开辟成功便返回开辟好的内存的首地址,开辟失败则返回NULL。

四、free

free函数的作用就是将malloc、calloc以及realloc函数申请的动态内存空间释放,其释放空间的大小取决于之前申请的内存空间的大小。

我们今天主要说说C++中动态内存管理方式:

3.C++中动态内存管理方式

首先,C语言内存管理的方式在C++中可以继续使用。但有些地方不够完善而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

new和delete操作内置类型

一、动态申请单个某类型的空间

//动态申请单个int类型的空间

int* p1 = new int; //申请

delete p1; //销毁

其作用等价于C语言中的:

int* p2 = (int*)malloc(sizeof(int)); //申请

free(p2); //销毁

区别在于:

1.C语言的malloc属于库函数,C++中属于操作符 ,同时new/delete也是两个关键字

2.如果动态申请的对象是内置类型,用malloc和new没区别,如果动态申请的对象是自定义类型,有区别

new和delete操作自定义类型

new/delete不仅仅会开空间/释放空间,还会调用构造函数和析构函数

举个例子:

#include

using namespace std;

class A

{

public:

A(int a=0)//构造

:_a(a)

{

cout << “A()” << endl;

}

~A()//析构

{

cout << “A()” << endl;

}

private:

int _a;

};

int main()

{

A* p4 = new A(10);//申请空间,传参(10),调用构造函数对开的空间初始化

delete(p4);

return 0;

}

通过监视可以看到申请的空间初始化为了10

在这里插入图片描述

动态申请多个类的空间

用new和delete操作符:

Test* p3 = new Test[10]; //申请,调用十次构造函数

delete[] p3; //销毁

用malloc和free函数:

Test* p4 = (Test*)malloc(sizeof(Test)* 10); //申请

free(p4); //销毁

注意:

  • 申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[]

  • 在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc和free不会

  • 建议在C++中无论是内置类型还是自定义类型的申请和释放,尽量都使用new和delete。

  • 申请(malloc new int[] new int)和 释放(free delete[] delete)一定要匹配使用,否则可能会导致崩溃

4.operator new和operator delete函数

————————————————

粗略理解:

new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new和delete在底层是通过调用全局函数operator new和operator delete来申请和释放空间的。

————————————————

operator new():指对new的重载形式,它是一个函数。并不是运算符。对于operator new的重载方式而言,分为两种,一种是全局重载而另一种是类重载。

全局重载 void* ::operator new(size_t size)

在类中重载 void* A::operator new(size_t size)

实际上:

  • operator new的底层是通过调用malloc函数来申请空间的,当malloc申请空间成功时直接返回;若申请空间失败,则尝试执行空间不足的应对措施,如果该应对措施用户设置了,则继续申请,否则抛异常

  • operator delete的底层是通过调用free函数来释放空间的,和free没有任何差别。

new和operator new()之间的关系(重点):

首先理解对于A* a = new A中到底干了些什么事情?

  1. 分配内存 ;
  1. 调用构造函数生成类对象;
  1. 返回相应指针。

第一步中分配内存的操作由operator new(size_t)来完成的,如果类A重载了operator new,那么将调用A::operator new(size_t ),如果没有重载,就调用::operator new(size_t )。

同理,operator new[]、operator delete、operator delete[]也是可以重载的。

new 不能被重载,它先调用operator new分配内存(要实现不同的内存分配行为,应该重载operator new,而不是new 。),然后调用构造函数初始化那段内存。

下面通过一张图来梳理一下他们之间的关系:

在这里插入图片描述

new和delete的实现原理

内置类型

如果申请的是内置类型的空间,new/delete和malloc/free基本类似,不同的是,new/delete申请释放的是单个元素的空间,new[ ]/delete [ ]申请释放的是连续的空间,此外,malloc申请失败会返回NULL,而new申请失败会抛异常。

自定义类型

  • new的原理

1、调用operator new函数申请空间。

2、在申请的空间上执行构造函数,完成对象的构造。

  • delete的原理

1、在空间上执行析构函数,完成对象中资源的清理工作。

2、调用operator delete函数释放对象的空间。

  • new T[N]的原理

1、调用operator new[ ]函数,在operator new[ ]函数中实际调用operator new函数完成N个对象空间的申请。

2、在申请的空间上执行N次构造函数。

  • delete[ ] 的原理

1、在空间上执行N次析构函数,完成N个对象中资源的清理。

2、调用operator delete[ ]函数,在operator delete[ ]函数中实际调用operator delete函数完成N个对象空间的释放。

5.定位new表达式(placement-new)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

使用格式:

new(place_address)type 或者 new(place_address)type(initializer-list)

其中place_address必须是一个指针,initializer-list是类型的初始化列表。

使用场景:

定位new表达式在实际中一般是配合内存池使用,因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,就需要使用定位new表达式进行显示调用构造函数进行初始化。

#include

using namespace std;

class Test

{

public:

Test()
_data(0)

{

cout<<“Test():”<<this<<endl;

}

~Test()

{

cout<<“~Test():”<<this<<endl;

}

private:

int _data;

};

void Test()

{

// pt现在指向的只不过是与Test对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行

Test* pt = (Test*)malloc(sizeof(Test));

new(pt) Test; // 注意:如果Test类的构造函数有参数时,此处需要传参

}

6.内存泄漏

什么是内存泄漏,内存泄漏的危害?

内存泄漏:

内存泄漏是指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

我们来看一个例子:

在32位下运行下面的程序:

在这里插入图片描述

我们看到申请了1G的内存,但是没进行释放

在这里插入图片描述

我们在性能中也明确看到运行一次内存从5.8GB变到了4.8GB,如果多次运行,按理说每次都会造成1G的内存泄露。但是事实是多次运行可用内存还是4.8GB,对我们系统也好像没有影响。

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

mage/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBARW5qb3kgc29saXR1ZGUt,size_20,color_FFFFFF,t_70,g_se,x_16)

我们在性能中也明确看到运行一次内存从5.8GB变到了4.8GB,如果多次运行,按理说每次都会造成1G的内存泄露。但是事实是多次运行可用内存还是4.8GB,对我们系统也好像没有影响。

[外链图片转存中…(img-MAwWUW1w-1715725971850)]
[外链图片转存中…(img-fqbbGlXd-1715725971850)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值