zoukankan      html  css  js  c++  java
  • malloc、realloc和new你明白了么?

    //========================================================================
    //TITLE:
    //    malloc、realloc和new你明白了么?
    //AUTHOR:
    //    norains
    //DATE:
    //    Saturday  05-January-2008
    //Environment:
    //    VS2005 +
     SDK-WINCE5.0-MIPSII   
    //    EVC + SDK-WINCE5.0-MIPSII  
    //========================================================================
        malloc和realloc是C标准函数,而new是C++的关键字,三者都能动态分配内存.但其中一些有意思的细节,你注意了么?
        
        在开篇之前,我们首先需要明确一个概念,数据存储在内存中是无针对性的,换句话说,内存里面的数据,究竟是解释为字符串还是解释为整数,甚至是一个DWORD值还是一个拥有两个WORD的数值,它都是不知道的.如何解释内存中的数据,只和指向这段内存的指针有关.
        
        我们可以用以下代码验证:
     

    int WINAPI WinMain(    HINSTANCE hInstance,
                        HINSTANCE hPrevInstance,
                        LPTSTR    lpCmdLine,
                        
    int       nCmdShow)
    {
    #define MAX_SIZE_MALLOC            8

        BYTE 
    *pBuf = (BYTE *)malloc(MAX_SIZE_MALLOC);
        memset(pBuf 
    + 0,0x17,1);
        memset(pBuf 
    + 1,0x4f,1);
        memset(pBuf 
    + 2,0xBA,1);
        memset(pBuf 
    + 3,0x4E,1);
        memset(pBuf 
    + 4,0x9B,1);
        memset(pBuf 
    + 5,0x52,1);
        memset(pBuf 
    + 6,0x00,1);
        memset(pBuf 
    + 7,0x00,1);

        WCHAR 
    *pStr = (WCHAR *) pBuf;
        wprintf(L
    "Wide-String : %s ",pStr);


        
    int *pInt = (int *)pBuf;
        
    for(int i = 0 ; i < MAX_SIZE_MALLOC / sizeof(int); i ++)
        {        
            printf(
    "pInt[%d]: %d ",i,pInt[i]);        
        }

        free(pBuf);

        Sleep(
    1000);
    }


        输出结果如下:
        Wide-String : 众人力
        pInt[0]: 1320832791
        pInt[1]: 21147

        
        同样的的内存,只是因为指向的指针类型不同,所输出的结果迥然各异:因为pStr为WCHAR指针,所以将其解释为字符串,输出"众人力";而pInt为int类型指针,而指向的内存大小恰好等于两个int空间,因此又可以采用数组下标的方式获取数值.
            
        了解内存储存的无针对性之后,下面的内容就简单多了.
        
        
        首先我们需要知道内存空间的计量单位.一般来说,内存分配函数都是以BYTE(字节)为计量单位,如果我们分配两个BYTE的内存,代码则将是如此:

        PVOID pBuf = malloc(2);
        
        知道这个,下面所要说到的例子就好理解了.
        
        假设我们有个WCHAR数组,我们需要在使用之前将其全部置0,如果是静态分配,那则是非常简单:
        WCHAR pszNew[MAX_COUNT] = {0};

        
        但如果是用new分配的呢?因为用new动态分配无法初始化,所以我们需要手动置0,可能很多朋友的第一想法是如此:
        for(int i = 0; i < MAX_COUNT; i ++)
        {
          pszNew[i] 
    = 0;
        }

        如果MAX_COUT比较大,那估计耗费在置0的时间上不是小数.其实,我们完全可以采用memset替代这个循环.而用memset最重要的一点是,我们需要知道pszNew新分配的数组占了多大的内存空间.不过,这也非常简单.一个WCHAR占据的内存为sizeof(WCHAR),则MAX_COUNT个为MAX_COUNT * sizeof(WCHAR).所以上面的代码可以用memset改写成:
        memset(pszNew,0,MAX_COUNT * sizeof(WCHAR));

        理解这个内存存储空间后,我们也不难明白将pszNew写到文件中的代码为何如此了:
        WriteFile(hFile,pszNew,MAX_COUNT * sizeof(WCHAR),&dwWritten, NULL);

        malloc和new都可以动态分配内存,那在实际中如何取舍?一般来说,如果空间是一次性分配,并且不需要再对已分配内存再次进行大小分配,推荐使用new,否则就应该用malloc.
        
        举个例子比较容易理解.假如我们需要分配一个动态内存保存字符串pszA,然后不久之后又有一个字符串pszB送来,而这时需要在原有的内存基础上再追加pszB.如果采用new分配内存,则代码可能会如此:
            
        ...

        
    //这代码段用来存储pszA
        
    //pBuf指向存储的地址
        TCHAR *pBuf = new TCHAR[_tcslen(pszA) + 1];
        _tcscpy(pBuf,pszA);  
        
        ...  

        
    //下面代码追加pszB
        TCHAR *pNew = new TCHAR[_tcslen(pBuf) + _tcslen(pszB) + 1];
        _tcscpy(pNew,pBuf);
        _tcscat(pNew,pszB);
        delete [] pBuf;
        pBuf 
    = pNew;

        如果pBuf内存是用malloc分配的,因为可以使用realloc在保持原有数据的基础上重新分配内存,故代码显得更为精炼:
        ...
        
        
    //这代码段用来存储pszA
        TCHAR *pBuf = (TCHAR *)malloc((_tcslen(pszA) + 1* sizeof(TCHAR));
        _tcscpy(pBuf,pszA);

        ...
        
        
    //下面代码追加pszB
        pBuf = realloc(pBuf,(_tcslen(pBuf) + _tcslen(pszB) + 1* sizeof(TCHAR));
        _tcscat(pBuf,pszB);


        既然realloc这么方便,那么可不可以先用new分配内存,然后再用realloc重分配呢?最好不要如此.这点在MSDN中描述得很清楚,如果用new分配的内存只能用delete,相对malloc和realloc也只能用free.那如果用free释放new分配的内存会是一种什么结果呢?C++标准中关于这个行为未定义,也就是说,可能没问题,但也不排除出现异常的可能.所以,我们还是老老实实按照建议行事吧.
        
        虽然接下来的内容看似主题无关,但毕竟还是和内存有千丝万缕的联系,所以在这也多说两句,就当成是文章的结尾吧.
        
        给一个变量赋值,给我们的第一直觉是采用"=",这也是最常用的方法,如果想比较BT,你还可以采用memset.就以文章开头的代码做例子为承接而结束全文吧:
        //以下每段代码都等价:
        *pBuf = 0x17;
        pBuf[
    0= 0x17;
        memset(pBuf 
    + 0,0x17,1);

     

    转自:http://blog.csdn.net/song_0521/archive/2009/09/22/4579596.aspx

    C语言中的realloc函数功能用C++怎么实现?

    定义一个函数,在里面,一个指针存指向你本来指针的内存,然后delete本来指针,重新分配你后来需要的内存,然后用memcpy这个函数把本来指针的内容存放到新分配的内存中去,然后delete那个临时的指针,然后返回重新定义的指针就可以了

  • 相关阅读:
    Android 主题theme说明 摘记
    Android开发 去掉标题栏方法 摘记
    安卓项目五子棋代码详解(二)
    关于 ake sure class name exists, is public, and has an empty constructor that is public
    百度地图3.0实现图文并茂的覆盖物
    android onSaveInstanceState()及其配对方法。
    关于集成科大讯飞语音识别的 一个问题总结
    android 关于 webview 控制其它view的显示 以及更改view数据失败的问题总结
    C# 解析 json Newtonsoft果然强大,代码写的真好
    c#数据类型 与sql的对应关系 以及 取值范围
  • 原文地址:https://www.cnblogs.com/zhwl/p/2762171.html
Copyright © 2011-2022 走看看