内存分配函数该怎么写?指针传递也发生拷贝?

内存分配函数该怎么写?指针传递也发生拷贝?

需求:我们想写一个函数,这个函数用于内存的创建,返回指向内存的指针,这个函数该怎么写?

我们试着来写一下:

int *getMemory(int *ptr)
{
    ptr = new int;
    return ptr;
}

int main()
{
    int *p = nullptr;
    getMemory(p);
    if (p == nullptr)
        cout << "内存分配失败!" << endl;
    else
    {
        cout << "内存分配成功!" << endl;
        delete p;
    }
    return 0;
}

getMemory函数传入int*类型的指针,在函数体内创建内存,返回指向该内存的地址。看似函数写的没有错,运行之后,会输出:

内存分配失败!

显然,这个函数写错了,并且造成了内存泄漏,其实我们知道这个函数写的不对,但是为什么不对,又该怎么写呢?

让我们来测试另外一个用例:

int num1 = 4;
int num2 = 5;

void func(int *ptr)
{
    ptr = &num2;
    cout << *ptr << endl;
}

int main()
{
    int *p = &num1;
    cout << *p << endl;

    func(p);
    cout << *p << endl;
    return 0;
}

上面的函数大体的意思为:有一个指针,指向num1,通过函数func,将指针指向了num2,之后又输出了指针对应的值。因为指针p在中途改变了指向,那么输出应为:4 5 5

然而输出为:4 5 4。这又是为什么呢?

其实,当指针作为参数的时候,在传递指针变量的时候也发生了拷贝,跟值传递是一样的,它拷贝的就是这个指针,并且这个拷贝后的指针与原来的指针指向同一块内存。这就出现了两个指针同时指向一块内存的情况,一个是原指针,另一个是拷贝后的指针,拷贝后的指针在函数调用结束后就不存在了。

知道了以上的原理,就不难解释上面的问题了。

p指针指向num1,在调用函数的时候,p指针发生拷贝,生成了ptr,在函数体内,指针ptr并没有操作原来指向的内存,而是又指向了另一块内存num2,这时候ptrp没有了关系,在函数调用结束之后,ptr被销毁,p指针还是指向原理的地址,并且没有进行任何操作,这就是输出4 5 4的原因了。

让我们再来解决第一个问题,与第二个问题类似,在调用函数之后,p指针发生了拷贝,生成了ptrptr又指向了另外被分配的区域,但它与p就没关系了,所以在函数返回之后,指针p依旧为nullptr

那正确的分配内存的函数该怎么写呢?

我们知道了传递指针会发生拷贝,被拷贝后的指针再指向其他的地址对原指针产生不了任何作用,那我们就应该让原指针与拷贝后的指针指向的依然是同一地址,那么拷贝后的指针再去指向别的区域,原指针也会同样指向该内存。

为了让它们的地址相同,所以要传递二级指针。

那正确的写法:

int *getMemory(int **ptr)
{
    *ptr = new int;
    return *ptr;
}

int main()
{
    int *p = nullptr;
    getMemory(&p);
    if (p == nullptr)
        cout << "内存分配失败!" << endl;
    else
    {
        cout << "内存分配成功!" << endl;
        delete p;
    }
    return 0;
}

上面的代码就会输出**内存分配成功!**,这个函数就写正确了。

复盘一下,在函数中,我们传递了指针的指针,在发生拷贝后,两个指针第二级的地址是不同的,但第一级指针都同时指向了一块地址,这就使得内存分配成功了。

总结:

在传递指针的时候,指针也会发生拷贝动作,使两个指针指向同一内存区域,可以对该内存区域进行修改,但拷贝后的指针指向其他内存,与原指针就无关了。

要想正确的分配内存,需要传递二级指针,保证二级指针指向的一级地址是相同的。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值