C/C++内存分配
我们知道C/C++内存的分配区域划分为栈, 内存映射段, 堆, 数据段, 代码段
这里简单介绍一下:
栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。
内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)
堆用于程序运行时动态内存分配,堆是可以上增长的。
数据段–存储全局数据和静态数据。
代码段–可执行的代码/只读常量。
了解了内存划分我们看一下下面的这个题目
![![[Pasted image 20260514170932.png]]](/https://i-blog.csdnimg.cn/direct/35be5815c6284b5894b5490ba5ca39dd.png)
请分析图中变量在内存中的存储位置及其所属的内存段。
![![[Pasted image 20260514172009.png]]](/https://i-blog.csdnimg.cn/direct/e7fe3abd5e394f7a8e1e5cdafd9f3826.png)
这里不好理解的是char2 *char2
*char 是字符串首元素, 那么只要知道字符串在哪储存就行了这字符串字面量它存储在代码块, 而char2 是局部变量定义在栈上的一个空间, 用来储存字符串字面量的地址
同理 pChar3 也是一个局部指针变量存储在栈上,它指向也是在代码段的字符串字面量
ptr1也是如此, ptr1指向在堆上分配的内存,而ptr1本身作为局部变量存储在栈上
C语言动态内存管理
C++内存管理
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
C++的new 和我delete 都是操作数并不是函数
new是用来动态开辟空间的
delete是用来释放空间的, 接下我们详细介绍一下.
new delete 操作内置类型
void Test()
{
int* ptr = new int;
int* ptr1 = new int(5);
int* ptr2 = new int[5] {1,2,3,4,5};
delete ptr;
delete ptr1;
delete[] ptr2;
}
int main()
{
Test();
return 0;
}
![![[Pasted image 20260514175035.png]]](/https://i-blog.csdnimg.cn/direct/205027361b614d6b8e967993eb78945d.png)
注意我们使用的时候要匹配使用
这时我们会有疑问, 既然new和malloc都是在堆区申请内存, 那么他们有什么区别呢???
![![[Pasted image 20260516172027.png]]](/https://i-blog.csdnimg.cn/direct/e1d03915a784470cad8bcf17b46bf987.png)
new/delete 操作自定义类型
![![[Pasted image 20260517131849.png]]](/https://i-blog.csdnimg.cn/direct/8b982d7df098413bac9da6a24a78ebb7.png)
new/delete 和 mal1oc/free最大区别是 new/delete对于自定义类型除了开空间还会调用构造函数和析构函数
operator new 和operator delete 函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数.
new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
也就是new 表达式做两件事:
1. 调用operator new 函数分配原始内存
2. 在该内存上调用构造函数
delete表达式做两件事:
1.调用析构函数
2.调用operator delete 释放原始内存
_GLIBCXX_WEAK_DEFINITION void*operator new (std::size_t sz) _GLIBCXX_THROW(std::bad_alloc)
{
void* p;
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
p = (void*)malloc(sz);
// ... 失败后调用 new_handler 并重试 ...
return p;
}
_GLIBCXX_WEAK_DEFINITION void
operator delete(void* ptr) noexcept
{
std::free(ptr);
}
通过上述两个全局函数的实现知道,operator new实际也是通过malloc来申请空间,
如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete最终是通过free来释放空间的。
new / delete的实现原理
内置类型
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
自定义类型
- new的原理
- 调用operatornew函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
- delete的原理
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete函数释放对象的空间
- new T[]的原理:
- 调用operator new[]函数,在operator new[]中实调用operator new函数完成N个对象空间的申请
- 在申请的空间上执行N次构造函数
- delete[]的原理:
- 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
- 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间
mallo/free 和 new/delete的区别
malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:
-
malloc和free是函数,new和delete是操作符
-
malloc申请的空间不会初始化,new可以初始化
-
malloc申请空间时,需要手动计算空间大小并传递new只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可
-
malloc的返回值为void*,在使用时必须强转,new不需要,因为new后跟的是空间的类型5.malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
-
申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理释
所以后申请空间可以尽量使用new和delete.
结语
``
new 和delete 的底层原理和简单用法就这么多, 希望大家通过这篇文章可以对new和delete有一个基础的认识, 谢谢大家观看, 有不足的地方也希望大家积极讨论

1545

被折叠的 条评论
为什么被折叠?



