C++ 传递动态内存

目前以看程序员面试宝典的开被相遇了传递动态内存的题材。

#include <iostream>
using namespace std;
void GetMemory(char *p,int num)
{
    p=(char *)malloc(sizeof(char) * num);
}
void Test(void)
{
    char *str=NULL;
    GetMemory(str,100);    //str仍然为NULL
    strcpy(str,"hello");//运行错误
}
int main()
{
    Test();
    return 0;
}

题上的说是:在函数GetMemory(char *p,int
num)中,*p实际上是主函数着str的一个副本,p申请了内存,只是把p指向的内存地址改变,而str并没有转,所以str仍然没拿走内存,在执行字符串复制时虽会出错。而且每一次p申请的内存都非会师拿到释放,最终会合招致内存泄露。

死了然,查找有关材料发现是价值传递及地方传递的题材。

当C语言中函数参数的传递出:值传递,地址传递,引用传递这两种样式。

1、值传递:形参是实参的正片,改变形参的价并无晤面影响外部实参的值。从为调用函数的角度来说,值传递是只为的(实参->形参),参数的值只可以传入,不可知传入。当函数内部用改参数,并且不指望之改变影响调用者时,接纳值传递。

独占鳌头代码:

#include <iostream>
using namespace std;
void swap(int p,int q)
{
    int temp;
    temp=p;
    p=q;
    q=temp;
    //cout<<p<<""<<q<<endl;
}
int main()
{
    int a=1,b=3;
    swap(a,b);
    cout<<a<<endl;
    cout<<b<<endl;
     return 0;
}

最终输出的结果a=1,b=3;可以看到a、b的值并没有转,实参a、b在传递参数为形参p、q的下,本身并无晤面转,最终形参的值未会师再一次又传回给实参,改变的是显得参p、q的价,实参a、b不会合来其他变动。注意在函数调用的早晚,参数的价传递只是将实参a、b的价传递给p、q,并无是用a、b取代形参p、q举行操作(这虽然是大家解的误区)。

2、地址传递:形参为指向实参地址之指针,当对形参的对操作时,就一定给对实参本身举行的操作。

#include <iostream>
using namespace std;
void swap(int *p,int *q)
{
    int temp;
    temp=*p;
    *p=*q;
    *q=temp;
    //cout<<p<<""<<q<<endl;
}
int main()
{
    int a=1,b=3;
    swap(&a,&b);
    cout<<a<<endl;
    cout<<b<<endl;
     return 0;
}

末段输出的结果a=3,b=1;达到了a、b交流的功能。函数swap(int
*p,int *q)中形参p、q均为指针,在函数引用的时节:swap(&a,&b);即一定给p=&a;q=&b;将a、b的地方赋值给了p、q,自然指针p指向了a,q指向了b,对*p,*q举行操作自为就是是对a、b的操作了,所以最终a、b的价值进行了置换。这尽管是地点传递(将a、b的地址传递让形参)。

3、引用传递:形参相当于是实参的“别名”,对形参的操作实际就是是指向实参的操作,在援传递过程被,被调函数的款式参数即便也作片变量在仓库中开发了内存空间,但是此时存放的是由于主调函数放进去的实参变量的地点。被调函数对形参的另操作都给拍卖成直接寻址,即经过栈中存放的地址访问主调函数中的实参变量。正因那样,被调函数对形参做的此外操作都影响了主调函数中之实参变量。

#include <iostream>
using namespace std;
void swap(int &p,int &q)//注意定义处的形式参数的格式与值传递不同
{
    int temp;
    temp=p;
    p=q;
    q=temp;
    //cout<<p<<""<<q<<endl;
}
int main()
{
    int a=1,b=3;
    swap(a,b);
    cout<<a<<endl;
    cout<<b<<endl;
     return 0;
}

末段输出的结果a=3,b=1;达到了a、b交流的功力。

  这我们若小心和价值传递的分别,函数定义之早晚swap(int
&p, int
&q);其中标注了形参为引用,在调用函数swap(a,b)的上举行参数传递,此时异常给&p=a;q=&b;即p为a的援,q为b的援,此时p、q就一定给a、b的别名,对p、q的操作也即是一贯对a、b的操作。

  回到最上边的代码处,在调用函数GetMemory(str,100)的当儿,str为指针,存储的吧地点,举行参数传递的时将str的地点传递让指针p,最起首指针p指向NULL,使用malloc开辟新的内存后,p就指向了初开发的内存空间,不过实参str并没改变,依然依靠于了NULL,p指向新开发的内存空间后也未曾自由,如此就招致了内存泄露,导致错误。

  对于修改章程发生二种修改章程。

1、使用引用。

#include <iostream>
#include <malloc.h>
#include <string.h>
using namespace std;
void GetMemory(char *&p,int num)
{
    p=(char *)malloc(sizeof(char) * num);
}
void Test(void)
{
    char *str=NULL;
    GetMemory(str,100);
    strcpy(str,"hello");//
     cout<<str<<endl;
}
int main()
{
    Test();

    return 0;
}

输出结果吗hello,符合预期期望。在函数定义时GetMemory(char*
&p,int
num),将指针p定义为援,在参数传递的时光&p=str,即p为指针str的别名,对指针p的操作为不怕是指向str的操作,所以指针str也会晤针对新开拓的内存空间。

2、使用函数再次来到值。

#include <iostream>
#include <malloc.h>
#include <string.h>
using namespace std;
char *GetMemory(char *p,int num)
{
    p=(char *)malloc(sizeof(char) * num);
    return p;
}
void Test(void)
{
    char *str=NULL;
    str=GetMemory(str,100);
    strcpy(str,"hello");
    //cout<<&str<<endl;
     cout<<str<<endl;
}
int main()
{
    Test();
    return 0;
}

输出结果为hello,符合预期期望。调用函数GetMemory(str,100);的时回来的凡借助针p,再以str=GetMemory(str,100);举办赋值,卓殊给str=p,即str也对了新开发的内存单元,不再对NULL,可以针对这个进行操作,最终输出大家所要之结果。

3、使用二级指针即针对指针的指针。

#include <iostream>
#include <malloc.h>
#include <string.h>
using namespace std;
void GetMemory(char **p,int num)
{
    *p=(char *)malloc(sizeof(char) * num);

}
void Test(void)
{
    char *str=NULL;
    GetMemory(&str,100);
    strcpy(str,"hello");
    //cout<<&str<<endl;
     cout<<str<<endl;
}
int main()
{
    Test();
    return 0;
}

输出结果为hello,符合预期期望。函数定义着GetMemory(char
**p,int
num),p为二级指针,在函数调用GetMemory(&str,100)进行价值传递的时节,此时分外给地点传递,指针*p=&str,*p存储的凡依针str的地方,我们由此修改*p即是修改了str的地点,将*p指向新开发的内存空间即是以str的地方指于了初开辟的内存空间,进而str也不怕本着了初开发的内存空间,从而达到了动态内存传递的力量。

char
*str=NULL;栈中操作的上,内存也内存为0x28ff2c的地址存储内容也NULL

图片 1

 

内存分配办法发生二种:

  • 打静态存储区域分配。内是程序编译的时光便早已分配好,这块内存在程序的成套运行期间都在。例如全局变量,static变量。
  • 在栈上创立。在推行函数时,函数内有些变量的存储单元都可以当栈上创设,函数执行了时这些存储单元自动为放出。栈内存分配运算内置于处理器的命集中,效用分外高,然而分配的内存容量有限。
  • 自堆积如山上分红,亦如动态内存分配。程序在运作的时节用malloc或new申请任意多少之内存,程序员自己承担在何时用free或delete释放内存。动态内存的生存期由我们决定,使用异常灵活。