当前位置:C++技术网 > 资讯 > 如何实现内存自动管理?

如何实现内存自动管理?

更新时间:2017-04-21 17:37:44浏览次数:1+次

char *c = new char(5);

*c = "1234";

假如c已经定义好了,现在c的内存也满了,该怎么往后添加字符或者字符串,如何new一个大内存赋值到c这个小内存上?


C++技术网会员解答:

    您好,感谢您对C++技术网的支持,如果觉得解答得不错,记得分享给其他朋友学习哦,一起学习效果更好。

    您的提问的内存使用,是内存自动扩展的案例。也就是说,给定一个初始内存,然后不断的往这块内存添加数据,如果数据量超过了内存的大小,那么就自动扩展内存大小,然后将内容添加在后面。对于上层使用来说,可以感觉不到动态内存的存在,就好像内存是无限大一样。C语言中我们可以通过realloc函数来重新分配内存,当然我们可以你先free再重新malloc。在C++就是new和delete。C++的string就是自动扩展内存的,内部实现已经这么做了。当然还有很多库里,都这么做了。动态内存扩展确实非常好,我们使用起来非常方便。

   那么下面我们来看看内存自动扩展,支持无限添加动态内存的功能原理和代码实现。

1.内存自动扩展原理

    首先我们给定一个初始内存,当添加字符串的时候,我们比较字符串占用的内存(不是字符串长度)和缓存可用的内存。如果可用内存不足以放下字符串,那么就需要扩展内存,如果放得下就直接添加字符串。扩展内存也就是重新分配一块新的内存,然后将老内存缓存里的数据转移到新的内存缓存里。多出来的空间,就可以用来放新增加的字符串。再将旧内存缓存释放。这样就完成了内存的扩展。

    至于扩展内存的时候,一次增加多少,这是策略问题。你可以一次增加1MB,也可以一次只增加1KB,也可以只增加字符串需要的大小。扩展内存必然倒是效率降低。如果大量的扩展内存,就会极大降低了效率。所以常见的做法就是当内存不够的时候,增加一大块内存,够使用一阵子了。这样不会频繁的增加内存,就提高了效率。

    我们后面的代码实现就按照字符串的大小来增加,这样的策略更节省内存。要使用什么策略,取决于你自己,取决于应用场景。不过只是增加内存的大小的差异而已,代码基本一样。

2.内存自动扩展实现代码

    我们先来看看整体的代码的流程:

#include "stdio.h"
#include "string.h"
char* addstr(char * str,int len);
//全局的缓存参数
int len_buf_all = 5;
int len_buf_left=5;
char *pbuf=0;
void main()
{
    //初始化缓存
    pbuf = new char[len_buf_all];
    memset(pbuf,0,len_buf_all);
    //准备字符串,并添加到缓存中,并返回缓存的指针
    char * str = "www.cjjjs.com";
    char *pStr = addstr(str,strlen(str));
    //打印缓存字符串
    printf(pStr);
    printf("\n");
    //准备第二个字符串,并继续添加到字符串缓存中,并返回缓存的指针
    char * str2 = "123456";
    pStr = addstr(str2,strlen(str2));
    //打印缓存字符串
    printf(pStr);
    printf("\n");
    delete []pbuf;
}
     可以看到,我们用pbuf作为内存缓存,len_buf_all记录缓存的总大小,len_buf_left记录缓存可用的大小。就这样,全局的变量就作为缓存,上任了。在main开始执行的时候,分配了内存,并初始化内存。在main快结束的时候,释放内存。addstr函数就是添加字符串,拼接在原有字符串的后面,函数返回拼接后的缓存的地址,我们可以直接打印出来。整体上,使用也很简单。

    那么关键的就是,内存的自动扩展和字符串的拼接的实现了,也就是addstr函数的功能。代码如下:

char* addstr(char * str,int len)
{
    //以极少的内存来存放新增的字符串,自动扩展缓存的大小。
    int len_str = len+1;
    if (len_str>len_buf_left)
    {
        //新字符串所占的内存比剩余缓存内存大,需要重新分配
        char * ptmp = new char[len_buf_all+len_str];
        memset(ptmp,0,len_buf_all+len_str);
        memcpy(ptmp,pbuf,len_buf_all);
        delete[] pbuf;

        len_buf_left+=len_str;
        len_buf_all+=len_str;

        pbuf = ptmp;
        strcat(pbuf,str);
        len_buf_left-=len_str;
    }
    else
    {
        //如果剩余缓存内存够拼接字符串,那么就继续使用
        strcat(pbuf,str);
        len_buf_left-=len_str;
    }
    return pbuf;
}
     实现思路很简单,我也做好了注释。需要注意的是,重新分配内存的时候,缓存的总大小和可用大小一定要记得同步更新。要记得释放旧缓存。缓存大小记录的变化,先后顺序不要搞错了。然后就是new数组的时候,使用new char[5],而不是new char(5)。