学习笔记13-C++-内存分配
来源:互联网 发布:极简网盘系统源码 编辑:程序博客网 时间:2024/05/21 22:25
malloc/free和new/delete 应用
C++有两组内存操作,分别是malloc/free和new/delete。new/delete是C++的操作符,malloc/free是C的函数。
new有两个作用:分配内存;调用类的构造函数。
delete也有两个作用:释放内存;调用类的折构函数。
而malloc和free只能分配和释放内存。
malloc/free的原型分别是:
void*malloc(size_t Size)//返回一个void类型的指针,具体使用的时候需要做类型转换。void*free(void *ptr)//参数是指针,释放该指针指向的内存。ptr=NULL//注意释放内存后应该把该指针指向NULL,防止后面再次使用这个指针。
原型很简单,但是需要注意,malloc申请的时候实际上占用的内存要比申请的大。因为超出的空间是用来记录对这块内存的管理信息——分配块的长度,指向下一个分配块的指针等等。这意味着越界使用动态分配的存储块,尤其是越界赋值,可能引起非常严重的后果。
而new/delete是C++的保留字,可以当做一个操作符。当然也不能越界。
注意new返回的指针是有类型的。
char*p = (char*)malloc(sizeof(char)*20);p = "abcdef";free(p);p = NULL;char *b = new char[20];b = "abcdefg";delete[]b;b=NULL;
上面两个代码的功能是一样的,都是动态分配一个char数组,容量是20。
下面再看看new/delete在类构造和折构中的应用:
//虚函数可以实现多态性//折构函数可以是虚函数,构造函数不行#include<iostream>using namespace std;class A{ public: int m=0,n=0; virtual void func()//虚函数 { cout<<"调用A类func函数"<<endl; } void func2() { cout<<"调用A类func2函数"<<endl; } //virtual void func3()=0;//纯虚函数,必须在继承类中定义 A() { cout<<"调用A类构造函数"<<endl; } A(int x,int y) { m=x; n=y; cout<<"调用A类有参构造函数"<<endl; } virtual ~A()//此处如果不声明为virtual,折构的时候就不会调用B的折构了,只会调用A的 { cout<<"调用A类折构函数"<<endl; }};class B:public A{ public: B() { cout<<"调用B类构造函数"<<endl; } void func() { cout<<"调用B类func函数"<<endl; } void func2() { cout<<"调用A类func2函数"<<endl; } void func3() { cout<<"调用B类func3函数"<<endl; } ~B() { cout<<"调用B类折构函数"<<endl; }};int main(){ A *a=new B(); a->func();//这里调用的是B类的func函数 a->func2();//这里调用的是A类的func2函数 //a->func3();//这里调用的是B类的func3函数 delete a;//此处会同时调用B和A的折构函数 cout<<endl; A *a2=new A(3,4); cout<<a2->m<<" "<<a2->n<<endl; delete a2; cout<<endl; A a3[3]; cout<<endl; //a3[1]=A(3,4); cout<<a3[1].m<<" "<<a3[1].n<<endl; return 0;}
运行上面代码可以看到,用new可以调用构造函数,但是不会自动折构,需要自己delete。
而使用传统方法定义类的话,会自动折构,不需要显式调用折构函数。
malloc/free 实现
这里参考”石锅拌饭”的博客
#include<unistd.h>#include<stdlib.h>struct memory{ int available;//1 available 0 not available int size;}mcb;void *memstart;//where available memory startvoid *lastaddr;//where is the last available addressint hasinit;//1 has init 0 has not initvoid init(){ lastaddr=sbrk(0);//有效内存的最尾端地址为堆尾地址 memstart=lastaddr; hasinit=1;}void *mymalloc(int num){ if(!hasinit) init(); void *current=memstart;//current ptr void *ret=NULL;//return ptr num+=sizeof(mcb);//在分配的内存基础上加上内存控制块结构体mcb的大小 while(current!=lastaddr) { mcb *pmcb=current;//定义一个控制块结构体的指针 if(pmcb->available&&pmcb->size>=num)//如果该块内存可用且大于要求分配的内存 { pmcb->available=0;//标记为已占用,not available ret=current;//返回这块地址的指针 break; } current+=pmcb->size;//不合适就跳过这块内存 } if(!ret)//如果没有找到可用内存块 { sbrk(num);//调整堆的尾部大小,增加一块大小是num的内存 ret=lastaddr;//将新增的这块内存返回 lastaddr+=num;//更新lastaddr mcb *pcb=ret;//设置这块新增加内存的控制信息 pcb->size=num; pcb->available=0; } ret+=sizeof(mcb);//返回的内存块要跳过控制结构体 return ret;}void myfree(void *start){ mcb *pmcb=(mcb*)(start-sizeof(mcb));//因为之前跳过了控制结构体,减去也就是指针指向控制体 pmcb->available=1;//将控制体信息置为available即可}int main(){ char *p=(char*)mymalloc(sizeof(char)*20); p="abcdef"; myfree(p); p=NULL; return 0;}
阅读全文
0 0
- 学习笔记13-C++-内存分配
- C语言学习笔记:内存分配
- c内存分配笔记
- C语言内存分配管理(学习笔记)
- C学习笔记——malloc内存分配
- C语言学习笔记——动态内存分配
- c语言学习笔记34之动态内存分配
- 郝斌老师c语言学习笔记----动态内存分配
- C/C++内存分配学习
- C++ 内存分配学习笔记
- JAVA 学习笔记-内存分配
- JAVA学习笔记--内存分配
- 翁恺C笔记|动态内存分配
- C的内存分配释放方式学习
- C内存分配的学习帖子
- C语言学习(6)---内存分配
- OpenSSL学习笔记——内存分配
- LDD3学习笔记(11):内存分配
- 初级排序算法(algs4)
- C程序编译过程浅析
- Selenium2+Python2.0自动化测试【6】 键盘事件
- 3d图形学中的uv坐标
- android开发让 actionbar 透明
- 学习笔记13-C++-内存分配
- 如何在系统应用中添加一个没有源码只有apk文件的应用模块
- Linux通过PID查看进程完整信息
- 多模式匹配算法-AC算法等
- RILJ层的语音注册和数据注册的解释
- 使用Android Studio查看应用签名信息
- 1055. 集体照
- mybatis的xml文件l,动态sql编写语法
- BZOJ 3670 动物园