为什么需要指针指针来在函数中分配内存

时间:2010-04-12 22:21:56

标签: c++ memory-management malloc

我在下面的代码中有一个分段错误,但在我将其更改为指向指针之后,它很好。有人能给我任何理由吗?

void memory(int * p, int size) {
    try {
        p = (int *) malloc(size*sizeof(int));
    } catch( exception& e) {
        cout<<e.what()<<endl;   
    }
}

它在主要功能中不起作用

int *p = 0;
memory(p, 10);

for(int i = 0 ; i < 10; i++)
    p[i] = i;

然而,它的工作原理如下。

void memory(int ** p, int size) {               `//pointer to pointer`
    try{
        *p = (int *)    malloc(size*sizeof(int));
    } catch( exception& e) {
        cout<<e.what()<<endl;   
    }
}

int main()
{
    int *p = 0;
    memory(&p, 10);       //get the address of the pointer

    for(int i = 0 ; i < 10; i++)
        p[i] = i;

    for(int i = 0 ; i < 10; i++)
        cout<<*(p+i)<<"  ";

    return 0;
}

9 个答案:

答案 0 :(得分:50)

因为您希望从函数中完成的操作中获取指针值 back malloc分配内存并为您提供该内存的地址。

在您的第一个示例中,您将该地址存储在本地参数变量p中,但由于它只是参数,因此不会将其返回到主程序,因为C / C ++是默认情况下按值传递 - 即使是指针。

Main      Function      malloc

  p         p            allocated
+---+     +---+         
| 0 |     | 0 |           A
+---+     +---+

becomes...

  p         p            allocated
+---+     +---+         
| 0 |     | ------------> A
+---+     +---+

因此当主读取p时,它变为0,而不是A.

在您的工作代码中,您遵循传递给地址的指针,该地址为您提供主程序中指针变量的位置。您更新该地址的指针值,然后主程序可以查找要用作其内存位置的值 - 从而将malloc返回的地址传递回主程序以供使用。

Main      Function      malloc

  p         p            allocated    
+---+     +---+         
| 0 |<------- |           A
|   |     |   |
+---+     +---+

becomes...

  p         p            allocated    
+---+     +---+         
|   |<------- |           
| ----------------------> A
+---+     +---+

因此当主读取p时,它得到A。

答案 1 :(得分:7)

指针存储数据存储的地址。将指针传递给函数意味着为其提供数据的地址。但是,在调用malloc之前,您没有数据地址。因此,您需要传递指针的地址(即指向指针的指针)。这允许memory获取指针p的地址,并将p设置为指向它为数据分配的内存区域。

答案 2 :(得分:3)

在C中,您只有按值传递。所以你的函数memory()得到它自己的p本地副本。内存中的malloc()仅将分配给函数本地的p的副本。当memory()返回main()时,main的p副本不变。在C ++中,您可以使用pass-by-reference来解决此问题,如下所示:

void memory(int*& p, int size)

在C中,您使用双指针来获得类似的结果。

答案 3 :(得分:2)

在你第一次打电话给记忆时:

void memory(int * p, int size)

意识到您将 VALUE 传递给memory(),而不是地址。因此,您将值'0'传递给memory()。变量p只是您传入的内容的副本... in包含相同的值,但 NOT 指向同一地址...

在你的第二个函数中,你传递了你的论点的 ADDRESS ...所以相反,p指向变量的地址,而不仅仅是你的副本变量。

所以,当你像这样调用malloc时:

*p = (int *)    malloc(size*sizeof(int));

您正在将malloc的返回值分配给p指向的变量的值。

因此,您的指针在内存()之外有效。

答案 4 :(得分:1)

第一个例子不起作用,因为指针参数不是main中的指针,它只是保持相同的值。

答案 5 :(得分:0)

你不需要使用指向指针的指针,但是引用的指针即*和&amp;不只是*

答案 6 :(得分:0)

您需要指向指针的指针,因为您需要返回新分配的指针的值。

有三种方法可以返回该值(如果使用C,则有2种方法):

  • 使用指针,这里是指针指针
  • 使用引用,这里是对指针的引用
  • 使用函数的返回值,因此make memory返回int *而不是void

第三种方式绝对是我的偏好。

(不是,我不会承认你也可以使用全球,这不是第四种方式,而是恐怖)。

答案 7 :(得分:0)

记忆(p,10); //获取指针的地址

这只是发送p值而不是p的地址。它发送(* p)。如果p 123的addrees及其值50,则向函数发送50。

并且在记忆功能中它使用新地址(如124)创建一个新指针,它包含50;并且它将分配内存并将分配的内存的开始写入124而不是123,因此主要的p仍然包含50.所以你什么都没做!您可以使用此代码控制此操作。

     #include<iostream>
    #include<conio.h>
    #include<exception>

    using namespace std;


    void memory(int* p, int size) {               //*************pointer to pointer` is a must**********
        try{
            p = new int[size] ;
            p[0]=100;
        } catch(bad_alloc &e) {
           cout<<e.what()<<endl;   
        }
    }

    int main()
    {
         int *p = 0;  ******you can do you should do this*******
        p = new int ; 
/* p = malloc( sizeof(int)); // this just change the value inside of p it is unnecessary 
and you will lose a adress from memory :) and possibly it will be unsafe if you free p may, you just 
free one adress*/
        /*before using a pointer always allocate it memory else
         you ll get frequent system crashes and BSODs*/
        memory(p, 10);       //get the address of the pointer//you are getting nothing
        cout <<p[0];
        //we set p[0] to 100 but it will write a garbage value here. 
        //because the value inside of p didn't change at the memory function
        //we sent just the value inside of p.

        getch();    
        return 0;
    }

答案 8 :(得分:-1)

我更正了代码..阅读评论,一切都将清楚..

#include<iostream>
#include<conio.h>
#include<exception>

using namespace std;


void memory(int* p, int size) {               //pointer to pointer` not needed
    try{
        p = new int[size] ;
    } catch(bad_alloc &e) {
       cout<<e.what()<<endl;   
    }
}

int main()
{
    // int *p = 0;  wrong .. no memory assigned and then u are passing it to a function
    int *p;
    p = new int ;  // p = malloc( sizeof(int));
    /*before using a pointer always allocate it memory else
     you ll get frequent system crashes and BSODs*/
    memory(p, 10);       //get the address of the pointer

    for(int i = 0 ; i < 10; i++)
        p[i] = i;

    for(int i = 0 ; i < 10; i++)
        cout<<*(p+i)<<"  ";

    getch();    
    return 0;
}