广州网站建设平台,跨境电商网站建设流程图,唯美图片wordpress主题,惠东网站建设W...Y的主页 #x1f60a;
代码仓库分享#x1f495; #x1f354;前言#xff1a; 我们之前在C语言中学习过动态内存开辟#xff0c;使用malloc、calloc与realloc进行开辟#xff0c;使用free进行堆上内存的释放。进入C后对于动态内存开辟我们又有了新的内容new与dele…
W...Y的主页
代码仓库分享 前言 我们之前在C语言中学习过动态内存开辟使用malloc、calloc与realloc进行开辟使用free进行堆上内存的释放。进入C后对于动态内存开辟我们又有了新的内容new与delete。今天我们来学习C中的动态内存开辟
我们先来进行一下内存管理的复习。
目录
C/C内存分布
C语言中动态内存管理方式malloc/calloc/realloc/free
C内存管理方式
new/delete操作内置类型
new和delete操作自定义类型
operator new与operator delete函数
new和delete的实现原理
内置类型 自定义类型
定位new表达式(placement-new)
C与new的使用场景 C/C内存分布
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);
}
1. 选择题选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)globalVar在哪里____ staticGlobalVar在哪里____staticVar在哪里____ localVar在哪里____num1 在哪里____char2在哪里____ *char2在哪里___pChar3在哪里____ *pChar3在哪里____ptr1在哪里____ *ptr1在哪里____globalVar在哪里C staticGlobalVar在哪里C staticVar在哪里C localVar在哪里A num1 在哪里A char2在哪里A *char2在哪里A pChar3在哪里A *pChar3在哪里D ptr1在哪里A *ptr1在哪里C
这些都是上述的答案全部是关于各种类型的数据在C中的存放位置。
【说明】 1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等栈是向下增长的。 2. 内存映射段是高效的I/O映射方式用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存做进程间通信。Linux课程如果没学到这块现在只需要了解一下 3. 堆用于程序运行时动态内存分配堆是可以上增长的。 4. 数据段--存储全局数据和静态数据。 5. 代码段--可执行的代码/只读常量。
C语言中动态内存管理方式malloc/calloc/realloc/free
void Test ()
{
int* p1 (int*) malloc(sizeof(int));
free(p1);
// 1.malloc/calloc/realloc的区别是什么
int* p2 (int*)calloc(4, sizeof (int));
int* p3 (int*)realloc(p2, sizeof(int)*10);
// 这里需要free(p2)吗
free(p3 );
}
相信大家对malloc与calloc非常熟悉唯一的区别就是参数不同还有就是calloc给予开辟空间初始化而malloc却没有。realloc是对calloc与malloc进行扩容的扩容分为异地扩容与原地扩容当目标位置空间足够时会进行原地扩容反之如果不够将进行异地扩容。
博主在之前的博客中详细讲解了C语言中的动态内存开辟如果有疑问可以点击下面链接进行学习C语言中动态内存管理方式malloc/calloc/realloc/free https://blog.csdn.net/m0_74755811/article/details/131820896?spm1001.2014.3001.5501
C内存管理方式
C语言内存管理方式在C中可以继续使用但有些地方就无能为力而且使用起来比较麻烦因 此C又提出了自己的内存管理方式通过new和delete操作符进行动态内存管理。
new/delete操作内置类型
void Test()
{// 动态申请一个int类型的空间int* ptr4 new int;// 动态申请一个int类型的空间并初始化为10int* ptr5 new int(10);// 动态申请10个int类型的空间int* ptr6 new int[3];delete ptr4;delete ptr5;delete[] ptr6;
}
通过上述代码可以看出使用new进行申请空间非常简单只需要new加上类型即可。如果我们想进行初始化即可在后面加上(n)即可。当进行开辟多个内存空间时我们像申请数组一样进行申请即可。但是在多个内存释放时一定要加上[]。 看到现在我们觉得malloc与new的功能差不多呀最多就是少些一些字母那为什么C还要创造一个新的字符进行学习呢我们接着往下看
new和delete操作自定义类型
class A
{
public:A(int a 0): _a(a){cout A(): this endl;}~A(){cout ~A(): this endl;}
private:int _a;
};
int main()
{
// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间
//还会调用构造函数和析构函数
A* p1 (A*)malloc(sizeof(A));
A* p2 new A(1);
free(p1);
delete p2;
// 内置类型是几乎是一样的
int* p3 (int*)malloc(sizeof(int)); // C
int* p4 new int;
free(p3);
delete p4;
A* p5 (A*)malloc(sizeof(A)*10);
A* p6 new A[10];
free(p5);
delete[] p6;
return 0;
}在内置类型中new与malloc是没有任何区别的而在自定义类型中就会体现出极大的不同。在自定义类型中malloc不会对开辟的成员对象进行初始化而new会自动调用构造函数。而在结束时delete会调研析构函数。所以说new与delete关键字就是为C面向对象而产生的
operator new与operator delete函数 new和delete是用户进行动态内存申请和释放的操作符operator new 和operator delete是 系统提供的全局函数new在底层调用operator new全局函数来申请空间delete在底层通过 operator delete全局函数来释放空间。
/*
operator new该函数实际通过malloc来申请空间当malloc申请空间成功时直接返回申请空间
失败尝试执行空 间不足应对措施如果改应对措施用户设置了则继续申请否
则抛异常。
*/
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p malloc(size)) 0)
if (_callnewh(size) 0){// report no memory// 如果申请内存失败了这里会抛出bad_alloc 类型异常static const std::bad_alloc nomem;_RAISE(nomem);}
return (p);
}
/*
operator delete: 该函数最终是通过free来释放空间的
*/
void operator delete(void *pUserData)
{_CrtMemBlockHeader * pHead;RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));if (pUserData NULL)return;_mlock(_HEAP_LOCK); /* block other threads */__TRY/* get a pointer to memory block header */pHead pHdr(pUserData);/* verify block type */_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead-nBlockUse));_free_dbg( pUserData, pHead-nBlockUse );__FINALLY_munlock(_HEAP_LOCK); /* release other threads */__END_TRY_FINALLYreturn;
}
/*
free的实现
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
通过上述两个全局函数的实现知道operator new 实际也是通过malloc来申请空间如果 malloc申请空间成功就直接返回否则执行用户提供的空间不足应对措施如果用户提供该措施 就继续申请否则就抛异常。operator delete 最终是通过free来释放空间的。
那我们就会有疑问new的底层逻辑就是mallocdelete的底层逻辑就是free。那么我们使用new开辟的空间能不能使用free进行释放呢
答案是可以但最好不要交叉使用。因为有时候程序会正常进行但是有时候就会报错。这是为什么呢
当我们使用new申请一块非常简单的空间只有一些基本的变量最多就是少调用了一层析构函数并不会影响空间的释放。但是当我们进行比如栈的开辟创建
class Stack
{
public:Stack(){cout Stack() endl;_a new int[4];_top 0;_capacity 4;}~Stack(){cout ~Stack() endl;delete[] _a;_top _capacity 0;}private:int* _a;int _top;int _capacity;
};
int main()
{Stack st;Stack* pst new Stack;delete pst;return 0;
} 第一种情况是指针指向在堆开好的空间只有两层关系而使用new进行开辟先在堆上开辟对象空间对象在使用构造函数进行初始化在堆上再开一层空间是三层的关系。如果我们要使用free进行释放空间只能将第二层进行释放而第三层就产生了内存泄漏
所以我们不要交叉使用做到一一对应
new和delete的实现原理
内置类型
如果申请的是内置类型的空间new和mallocdelete和free基本类似不同的地方是 new/delete申请和释放的是单个元素的空间new[]和delete[]申请的是连续空间而且new在申 请空间失败时会抛异常malloc会返回NULL。 自定义类型
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来释 放空间
定位new表达式(placement-new)
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。使用格式 new (place_address) type或者new (place_address) type(initializer-list) place_address必须是一个指针initializer-list是类型的初始化列表 使用场景 定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化所以如 果是自定义类型的对象需要使用new的定义表达式进行显示调构造函数进行初始化。
class A
{
public:
A(int a 0)
: _a(a)
{
cout A(): this endl;
}
~A()
{
cout ~A(): this endl;
}
private:
int _a;
};
// 定位new/replacement new
int main()
{
// p1现在指向的只不过是与A对象相同大小的一段空间还不能算是一个对象因为构造函数没
有执行
A* p1 (A*)malloc(sizeof(A));
new(p1)A; // 注意如果A类的构造函数有参数时此处需要传参
p1-~A();
free(p1);
A* p2 (A*)operator new(sizeof(A));
new(p2)A(10);
p2-~A();
operator delete(p2);return 0;
}
C与new的使用场景
虽然malloc与new都是在堆上进行开辟空间但是他们获取内存的方式不一样。malloc是需要多少就索取多少而new是”提前预支“内存这样就可以提高new的效率但是却导致了new空间浪费。所以说有利有弊我们应该在适当的情况使用适当的做法。
C中使用malloc和new有不同的用途和行为你可以根据需要选择哪个更适合你的情况。以下是一些情况下的推荐用法 使用malloc的情况
1.C兼容性 如果你编写的是C代码并且需要与C库或其他C代码进行交互使用malloc可能更合适因为malloc是C标准库函数。 2.需要手动管理构造和析构 malloc只分配内存不会自动调用构造函数或析构函数。如果你需要手动控制对象的构造和析构过程或者分配的内存不是用于存储对象例如分配原始字节数组则使用malloc。 3.需要明确指定内存大小 malloc接受一个字节数作为参数而new会考虑类型的大小和额外的构造函数开销。如果你需要确切控制内存分配的字节数可以使用malloc。 4.不需要类型检查 new是类型安全的而malloc不是。如果你需要执行类型不安全的操作可能需要使用malloc。
使用new的情况
5.C对象分配 如果你需要分配内存以存储C对象通常应使用new或new[]。new会自动调用对象的构造函数new[]用于动态分配数组并在必要时调用构造函数。 6.类型安全 new提供了类型安全性可以避免一些常见的内存错误例如内存泄漏和越界访问。 7.更简洁的语法 new和new[]的语法更简洁不需要显式指定分配的字节数。 8.自动内存管理 new分配的内存会在对象的生命周期结束时自动释放从而减少了内存泄漏的风险。
总的来说如果你编写纯粹的C代码并需要分配内存以存储对象通常建议使用new或new[]因为它们提供更好的类型安全性和内存管理。使用malloc通常是在需要更底层的内存分配控制或者与C代码进行交互时的情况。无论使用哪种方法都需要谨慎管理内存确保在不再需要时释放它以避免内存泄漏。 以上就是本次全部内容感谢大家观看