建设自己的网站,wordpress 切换主题,wordpress4.8是什么,注册好域名之后怎么做个人网站之前结束了类与对象#xff1a;今天进行下面部分内容的学习 文章目录 1.C/C内存分布2.C语言中动态内存管理方式#xff1a;malloc/calloc/realloc/free3.C动态内存管理方式3.1new/delete操作内置类型3.2new和delete操作自定义类型 4.operator new与operator delete函数5.new和…之前结束了类与对象今天进行下面部分内容的学习 文章目录 1.C/C内存分布2.C语言中动态内存管理方式malloc/calloc/realloc/free3.C动态内存管理方式3.1new/delete操作内置类型3.2new和delete操作自定义类型 4.operator new与operator delete函数5.new和delete的实现原理5.1内置类型5.2自定义类型 6.定位new表达式(placement-new)7.知识点梳理malloc/free和new/delete的区别 1.C/C内存分布 具体说明 栈又叫堆栈–非静态局部变量/函数参数/返回值等等栈是向下增长的。栈上的内存分配和释放是通过编译器生成的代码来管理的通常是通过在函数退出时进行清理来实现的内存映射段是高效的I/O映射方式用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存做进程间通信堆用于程序运行时动态内存分配堆是可以上增长的。堆上的内存通常需要手动管理需要显式地分配和释放堆上的内存数据段–存储全局数据和静态数据。全局数据和静态数据的销毁通常是在程序结束时由操作系统自动完成二者的生命周期也是整个程序代码段–可执行的代码/只读常量 下面根据具体代码来看
int globalVar 1;//全局变量在静态区
static int staticGlobalVar 1;//全局静态变量在静态区int main()
{static int staticVar 1;//局部静态变量在静态区。作用域只在这个函数内但是生命周期是在整个程序int localVar 1;//局部变量在栈int num1[10] { 1, 2, 3, 4 };//局部变量在栈char char2[] abcd; //局部变量在栈。//其实[]这个符号是把位于常量区的abcd拷贝到栈上再去指向const char* pChar3 abcd;//pChar3在栈上但是是直接指向常量区的abcd。所以*pChar3在常量区int* ptr1 (int*)malloc(sizeof(int) * 4);//ptr1这个指针变量还是在栈但是*ptr1是在堆上int* ptr2 (int*)calloc(4, sizeof(int));int* ptr3 (int*)realloc(ptr2, sizeof(int) * 4);free(ptr1);free(ptr3);return 0;
}那全局变量和全局静态变量的区别是 全局变量具有外部链接性可以被其他文件中的函数访问。 静态全局变量具有内部链接性只能被声明它的文件内的函数访问本文件 2.C语言中动态内存管理方式malloc/calloc/realloc/free
malloc()函数 功能malloc函数用于在堆上动态分配指定大小的内存空间。语法void* malloc(size_t size);返回值如果分配成功则返回指向分配内存的指针如果分配失败则返回NULL。 calloc()函数 功能calloc函数用于在堆上动态分配指定数量、指定大小的内存空间并将分配的内存空间初始化为0。语法void* calloc(size_t num, size_t size);返回值如果分配成功则返回指向分配内存的指针如果分配失败则返回NULL。 realloc()函数 功能realloc函数用于更改之前分配的内存块的大小可以扩大或缩小内存块的大小。语法void* realloc(void* ptr, size_t size);返回值如果分配成功则返回指向重新分配内存的指针如果分配失败则返回NULL。如果返回的指针与之前的指针不同意味着内存块的大小或位置可能已经改变了。 free()函数 功能free函数用于释放之前动态分配的内存空间将其返回给系统供其他程序使用。语法void free(void* ptr);返回值无。
异同点
malloc和calloc都用于分配内存但calloc在分配内存后会将其初始化为0而malloc不会。realloc用于更改之前分配的内存块的大小可以扩大或缩小内存块的大小而malloc和calloc只能用于分配新的内存块。free用于释放动态分配的内存将其返回给系统供其他程序使用 更加详细的介绍大家可以移步于我的文章 3.C动态内存管理方式 C语言内存管理方式在C中可以继续使用但有些地方就无能为力特别是关于自定义变量因此C又提出了自己的内存管理方式通过new和delete操作符进行动态内存管理 在C中new和delete是用于动态内存管理的运算符它们提供了对malloc、calloc、realloc和free等C语言内存管理函数的更高级的封装和功能。
new运算符 功能new运算符用于在堆上动态分配内存并调用对象的构造函数来初始化这块内存。语法new 类型 或 new 类型[大小]例如new int 或 new int[10]。返回值如果分配成功则返回指向分配内存的指针如果分配失败则抛出std::bad_alloc异常。 delete运算符 功能delete运算符用于释放由new分配的内存并调用对象的析构函数来销毁对象。语法delete 指针 或 delete[] 指针例如delete ptr 或 delete[] arr。返回值无。
与C语言中的malloc和free相比new和delete的优势在于
new和delete是运算符而不是函数因此它们可以重载从而实现自定义的内存分配和释放策略。new和delete会调用对象的构造函数和析构函数从而确保对象的正确初始化和清理。new和delete支持运算符重载可以用于自定义类的动态内存管理而malloc和free只能用于分配和释放原始内存块
3.1new/delete操作内置类型
直接上代码
int main()
{// 动态申请一个int类型的空间int* a new int;// 动态申请一个int类型的空间并初始化为11int* b new int(11);// 动态申请3个int类型的空间int* c new int[3];// 动态申请10个int类型的空间并进行部分初始化int* d new int[10]{ 1,2,3 };delete a;delete b;delete[] c;delete[] d;return 0;
}内置类型的对象申请释放new和malloc除了用法上没有区别 但是malloc不方便解决动态申请的自定义类型对象的初始化问题不会调用构造函数 3.2new和delete操作自定义类型
class A
{
public:A(int a0):_a(a){}~A(){cout 调用了~A() endl;}
private:int _a;
};int main()
{//动态申请一个A类型的空间A* pa1 new A(1);//动态申请3个A类型的空间A a1;A a2;A a3;A* pa2 new A[3]{ a1, a2, a3 };//可以直接写成以下两种A* pa3 new A[3]{ A(1), A(2), A(3) };//匿名对象//再少点A* pa4 new A[3]{ 1,2 ,3 };//隐式类型转换有单形参的构造函数支持delete pa1;delete[] pa2;delete[] pa3;return 0;
}new的本质开空间调用构造函数初始化 delete的本质析构函数释放空间 4.operator new与operator delete函数 new和delete是用户进行动态内存申请和释放的操作符operator new 和operator delete是系统提供的全局函数new在底层调用operator new全局函数来申请空间delete在底层通过operator delete全局函数来释放空间 大家注意啊这两个函数不是重载只是祖师爷把他们命名为这个他们是全局函数。
operator new该函数实际通过malloc来申请空间当malloc申请空间成功时直接返回申请空间失败尝试执行空间不足应对措施如果改应对措施用户设置了则继续申请否则抛异常。operator delete: 该函数最终是通过free来释放空间的
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{void* p;while ((p malloc(size)) 0)if (_callnewh(size) 0){static const std::bad_alloc nomem;_RAISE(nomem);}return (p);
}
void operator delete(void* pUserData)
{_CrtMemBlockHeader* pHead;RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));if (pUserData NULL)return;_mlock(_HEAP_LOCK);__TRYpHead pHdr(pUserData);_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead-nBlockUse));_free_dbg(pUserData, pHead-nBlockUse);__FINALLY_munlock(_HEAP_LOCK); __END_TRY_FINALLYreturn;
}看到其实operator new 实际也是通过malloc来申请空间。operator delete 最终是通过free来释放空间的 二者其实就是对malloc和free进行了封装加上了抛出异常的修饰 5.new和delete的实现原理
5.1内置类型 如果申请的是内置类型的空间new和mallocdelete和free基本类似不同的地方是 new/delete申请和释放的是单个元素的空间new[]和delete[]申请的是连续空间而且new在申请空间失败时会抛异常malloc会返回NULL。 5.2自定义类型 new的原理 调用operator new(跟malloc效果一样)函数申请空间在申请的空间上执行构造函数完成对象的构造 delete的原理 在空间上执行析构函数完成对象中资源的清理工作(先调用析构函数释放成员变量申请的空间不然会找不到)调用operator delete函数释放对象的空间 new TYPENAME[N]的原理 调用operator new[]函数在operator new[]中实际调用operator new函数完成N个对象空间的申请一次性申请在申请的空间上执行N次构造函数 delete[]的原理 在释放的对象空间上执行N次析构函数完成N个对象中资源的清理调用operator delete[]释放空间实际在operator delete[]中调用operator delete来释放空间 但是要注意一件事
class Stack
{
public:Stack(int capacity 3){cout 调用了构造函数 endl;_a new int[capacity];_top 0;_capacity capacity;}~Stack(){cout ~Stack() endl;delete _a;_a nullptr;_top -1;_capacity 0;}
private:int* _a;int _top;int _capacity;
};int main()
{Stack* a1 new Stack[10];cout sizeof(*a1);delete[] a1;return 0;
}实际上开了124个字节大家回想怎么会多4个呢不是 10 ∗ 12 10*12 10∗12吗 那四个字节来储蓄申请了几个对象这里就是10 6.定位new表达式(placement-new) 定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。 使用格式 new (place_address) type或者new (place_address) type(initializer-list) place_address必须是一个指针initializer-list是类型的初始化列表 使用场景 定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化所以如果是自定义类型的对象需要使用new的定义表达式进行显示调构造函数进行初始化 class Stack
{
public:Stack(int capacity 3){cout 调用了构造函数 endl;_a new int[capacity];_top 0;_capacity capacity;}~Stack(){cout ~Stack() endl;delete _a;_a nullptr;_top -1;_capacity 0;}
private:int* _a;int _top;int _capacity;
};int main()
{Stack* s1 (Stack*)operator new(sizeof(Stack));//都知道构造函数不能显示调用//s1-Stack();//但是可以使用定位new显示调用构造函数new(s1)Stack(2);//但是析构函数可以s1-~Stack();operator delete (s1);return 0;
}7.知识点梳理
malloc/free和new/delete的区别
malloc/free和new/delete的共同点是都是从堆上申请空间并且需要用户手动释放。不同的地
方是
malloc和free是函数new和delete是操作符malloc申请的空间不会初始化new可以初始化malloc申请空间时需要手动计算空间大小并传递new只需在其后跟上空间的类型即可如果是多个对象在[]中指定对象个数即可malloc的返回值为void*, 在使用时必须强转new不需要因为new后跟的是空间的类型malloc申请空间失败时返回的是NULL因此使用时必须判空new不需要但是new需要捕获异常申请自定义类型对象时malloc/free只会开辟空间不会调用构造函数与析构函数而new在申请空间后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理 前5条是用法上面的区别 最后一条是原理上的区别 这次内容就到这里啦下次会带来模版相关的知识感谢大家支持