C++内存机制学习总结

C++最烦人的一块就是其内存管理部分,也是C++的一个弊端,对于高手来说可以从中获得更好的性能,对于菜鸟来说简直就是噩梦的开始,因此向成为高手,内存管理着一块一定要过关,不象java和.NET他们的内存管理是自动的。本文从内存管理 内存泄漏 内存回收这三点出发分析下C++中内存的问题
1 内存管理:
在C++中,内存分成了五个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
 就是那些由new分配的内存块,他们的释放由应用程序去控制,如果程序员没有用delete释放的话,那么程序结束的时候操作系统自动回收
 在执行函数的时候,局部变量的存储单元都创建在栈上,函数执行完后这些存储单元自动的被释放
自由存储区 由malloc分配的内存块,和堆相似,不过自由存储区是通过free释放内存的
全局/静态存储区 全局变量和静态变量被分配到同一块内存中
常量存储区 里面存放的是常量,不允许修改
通过例子学习堆栈
void f(){
    int* p=new int[5];
}
f()函数的意思是:在栈内存中存放了一个指向一块堆内存的指针p。程序会先在堆中分配内存的大小,然后赶回这个内存的首地址放入栈中

对于类的内存分配new和delete操作应该这样书写:
class testclass{
public:
    void* operator new(size_t size);
    void operator delete(void* p);
};
void* testclass::operator new(size_t size){
    void* p=malloc(size);
    raturn p;
}
void testclass::operator delete(void* p){
    free(p);
}
我们也可以为单个的类重载new[]和delete[]操作符
class testclass{
public:
    void* operator new[](size_t size);
    void operator delete[](void* p);
};
void* testclass::operator new[](size_t size){
    void* p=malloc(size);
    return p;
}
void testclass::operator delete[](void* p){
    free(p);
}
int main(){
    testclass *p=new testclass[10];
    ...
    delete[] p;
}
常见的内存错误以及对其对策
内存未分配成功就使用了它,解决办法是在使用内存之前,首先检查内存指针是否为NULL语句如下:if(NULL==p)或者if(p!=NULL)
内存分配成功,但是没有初始化它 记着赋初值就可以了
操作越界了,注意不要越界就是了
没有释放内存,造成内存泄漏最后造成内存耗尽了,new/delete malloc/free操作必须成对的出现,free或者delete释放后的内存,将指针设置成NULL,否则就会出现野指针。
释放了内存却继续使用它 不要使用就是了
另外我们也不要在return的时候返回指向栈内存的指针和引用,因为该内存在函数体结束的时候被自动的销毁了。
指针和数组的问题:
虽然在C++中数组和指针有时候可以换着用,但是他们二者是不等价的
对于数组的复制不能简单的使用=操作符来完成b=a的复制,而不要通过strcpy()函数来完成复制,同样比较数组a和b是否相同,不要使用==操作符,需要使用标准库函数strcmp进行比较。
p=a并不能将a的内容复制给指针p,而是把a的地址赋给了p,如果需要复制a的内容,需要使用库函数malloc为p申请一个容量为strlen(a)+1的字符内存,然后用strcpr()函数进行复制
如果函数的参数是一个指针,不要指望用该指针去申请动态内存,例子:
void getmemory(char* p,int num){
    p=(char*)malloc(sizeof(char)*num);
}
void test(){
    char*str=NULL;
    getmemory(str,100);//str依然是NULL
    strcpy(str,"hello");
}
如果我们非要用指针参数去申请内存,那么可以使用“指向指针的指针”来完成
void getmemory(char** p,int num){
    *p=(char*)malloc(sizeof(char)*num);
}
void test(){
    char* str=NULL;
    getmemory(&str,100);
    strcpy(str,"www.jiaojiaoni.com");
    cout<<str<<endl;
    free(str);
}
上面是指向指针的指针分配内存的,因为这个概念不好理解,我们可以使用函数返回值的形式来传递动态内存,例子:
char* getmemory(int num){
    char* p=(char*)malloc(sizeof(char)*num);
    return p;
}
void test(){
    char* str=NULL;
    str=getmemory(100);
    strcpy(str,"www.jiaojiaoni.com");
    cout<<str<<endl;
    free(str);
}
return返回的只要不是指向栈内存的指针就可以,因为指向栈内存的指针在函数结束的时候就自己消亡了。
野指针
    野指针是指向垃圾内存的指针,if语句可以判断出NULL指针但是判断不出野指针
野指针形成的原因:
指针变量没有初始化 
指针变量在创建的同时应该被初始化,或者将指针设置成NULL,或者让它指向合法的内存
例如:
        char* p=NULL;
        char* str=(char*)malloc(100);
指针被free或者delete后 ,没有设置成NULL。指针释放的时候应该设置成NULL
指针越界操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值