冰冰学习笔记:new与delete

欢迎各位大佬光临本文章!!!

 

还请各位大佬提出宝贵的意见,如发现文章错误请联系冰冰,冰冰一定会虚心接受,及时改正。

本系列文章为冰冰学习编程的学习笔记,如果对您也有帮助,还请各位大佬、帅哥、美女点点支持,您的每一分关心都是我坚持的动力。

我的博客地址:bingbing~bang的博客_CSDN博客https://blog.csdn.net/bingbing_bang?type=blog

我的gitee:冰冰棒 (bingbingsupercool) - Gitee.comhttps://gitee.com/bingbingsurercool


系列文章推荐

冰冰学习笔记:《类与对象(下)》

冰冰学习笔记:《运算符重载---日期类的实现》


目录

系列文章推荐

前言

1.C/C++中的内存分布

2.C++中的内存管理方式

2.1内置类型处理

2.2自定义类型

3.operator new和operator delete

4.定位new

5.new和malloc以及delete与free的区别


前言

        在学习C语言时我们对动态内存申请与释放重点学习了几个函数,malloc、calloc、realloc、free。那么C++种是否含有这种类似的内存管理函数呢?答案是肯定的,只不过C++中兼容C语言的这些函数,并且C++又提出了两个关键字进行管理,new与delete。new关键字用来动态开辟,delete用来释放。

1.C/C++中的内存分布

        C/C++中的内存分布图如下图所示:

(1):又叫堆栈,非静态局部变量,函数参数,返回值等等,栈是向下增长的,由高地址向低地址延申。

(2)内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程间通信。

(3):用于程序运行时动态内存分配,堆是向上增长的,由低地址向高地址延申。

(4)BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

(5)数据段:存储已初始化的全局数据和静态数据,static修饰的变量一般存储在此。

(6)代码段:可执行的代码/只读常量,常量字符串存储位置。

 通过下面的例题来分析:

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);
}

        globalVar,staticglobalVar都是全局变量,并且staticClobalVar被static修饰成为静态全局变量,因此二者都存储于数据段中。staticVar本来是局部变量,但是被static修饰后变为静态局部变量,存储于数据段。localVar,num1,char2,pchar3,ptr1,ptr2,ptr3都是在栈上开辟的局部变量,只是指针指向的内容不同。char2是个数组,数组内容被字符串进行初始化,但是内容还是存在于栈上。pchar3指向一个常量字符串,因此*pchar3指向的内容存储于常量区,也就是代码段,*pchar3同理。*ptr1,*ptr2,*ptr3指向的内容均为在堆上开辟的空间。

2.C++中的内存管理方式

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

2.1内置类型处理

        对于内置类型,new和delete与malloc和free并无本质区别,只有使用方法的区别。new的使用方法简单,并且不用计算字节大小,只需后面跟开辟类型即可。delete后只需跟上指针。

int main()
{
	int* p1 = new int;//开辟一个int空间
	int* p2 = new int(5);//开辟一个int空间并初始化为5
	int* p3 = new int[5];//开辟5个int空间
	int* p4 = new int[5]{ 1,2,3 };
	//开辟5个空间,前三个初始化为1,2,3,剩余的为0;
	delete p1;
	delete p2;
	delete[] p3;//释放多个空间
	delete[] p4;
	return 0;
}

2.2自定义类型

        之所以C++要使用new和delete是在于对自定义类型处理时,new于delete不仅完成了申请和释放的工作,还调用了对象的构造函数和析构函数对其进行了初始化和清理

        并且,new在开辟空间失败时会抛异常而不是像malloc一样返回空指针。

class A
{
public:
	A(int a = 0)
		:_a(a)
	{ 
		cout << "A(int a=0)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{

	A* p3 = new A(3);//开辟一个A类型的空间并调用构造函数初始化为3
	A* p4 = new A[10]{ {1},{2},{3},{4} };//开辟多个并构造
	A* p5 = new A[5]{ A(10),A(20) };//开辟多个并构造
	delete p3;
	delete[] p4;
	delete[] p5;
    return 0;
}

        在使用new与delete时,一定要注意类型匹配,new申请的是数组,delete释放时就需要加上  [ ]释放,避免错误。

3.operator new和operator delete

        这两个函数是系统提供的全局函数,new与delete在开辟和释放空间的时候会自动调用这两个全局函数。底层逻辑还是使用malloc开辟的空间,还是去调用的free释放。

 

        我们可以自己重载这两个函数用来实现特殊的功能,比如将开辟空间和释放空间的代码文件记录到日志中。

        实际上我们可以主动调用这两个函数进行空间开辟,但是没有必要,直接使用new和delete即可。

int* p= (int*)operator new (20);//主动调用
	operator delete(p);

4.定位new

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

        我们现阶段能够调用构造函数的方法只有创建对象和用new开辟空间时可以调用,当我们使用malloc申请一个自定义类型的空间时,没有办法调用构造函数进行初始化,此时我们就可以使用定位new进行初始化。

class A
{
public:
	A(int a = 0)
		:_a(a)
	{ 
		cout << "A(int a=0)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = (A*)malloc(sizeof(A));
	A* s = (A*)malloc(sizeof(A));
	new (p)A;
	new (s)A(20);//初始化值为20
	p->~A();//调用析构清理
	free(p);
	s->~A();//调用析构清理
	free(s);
	return 0;
}

 5.new和malloc以及delete与free的区别

 new的原理:

        调用operator new开辟空间,再调用构造函数完成对象构造。

delete的原理:

        在空间上先执行析构函数,完成对象的清理工作,然后调用operator delete释放对象空间。

new T [N]的原理:

        调用operator new[ ]函数,在operator new[ ]中实际调用operator new函数完成N个对象空间的申请,在申请的空间上执行N次构造。

delete [ ]的原理:

        先在空间上执行N次析构函数,完成N个对象中的清理,然后调用operator delete[ ]释放空间,实际在operator delete[]中调用operator delete来释放空间。

区别:

(1)malloc和free是函数,new和delete是操作符

(2)malloc申请的空间不会初始化,new可以初始化

(3)malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可, 如果是多个对象,[]中指定对象个数即可

(4)malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型

(5)malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常

(6)申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new 在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我会尽力回答你的问题。关于通过UDP传输音视频,我了解一些相关的知识,下面是一些学习笔记: 1. gstreamer是一个流媒体框架,用于创建、处理和播放多媒体流。它支持多种音视频格式,可以通过插件扩展功能。 2. 通过gstreamer可以使用UDP协议传输音视频数据。UDP协议是一种无连接的协议,不保证数据传输的可靠性和顺序性,但是传输效率高。 3. 首先需要创建一个gstreamer的pipeline,包括音视频源、编码器、UDP发送端等组件。例如: ``` gst-launch-1.0 -v filesrc location=test.mp4 ! decodebin ! x264enc ! rtph264pay ! udpsink host=192.168.1.100 port=5000 ``` 这个pipeline的作用是从test.mp4文件读取音视频流,解码后使用x264编码器进行压缩,然后使用rtph264pay将数据打包成RTP数据包,最后通过udpsink发送到指定的IP地址和端口。 4. 接收端需要创建一个gstreamer的pipeline,包括UDP接收端、解包器、解码器等组件。例如: ``` gst-launch-1.0 -v udpsrc port=5000 ! application/x-rtp, payload=96 ! rtpjitterbuffer ! rtph264depay ! avdec_h264 ! autovideosink ``` 这个pipeline的作用是从UDP端口5000接收音视频数据,使用rtpjitterbuffer解决网络抖动问题,使用rtph264depay将RTP数据包解包成原始的H.264数据流,然后使用avdec_h264解码器进行解码,最后使用autovideosink播放视频。 5. 在实际使用过程中,还需要考虑数据的带宽限制、网络延迟等问题,以保证音视频传输的效果。 希望这些笔记能对你有帮助。如果你还有其他问题,可以继续问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bingbing~bang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值