Astaboom
Astaboom

Reputation: 317

confusion with passing arrays by reference using pointers

I just asked a question several hours ago, and I have been utterly confused with something pointed out in the answers (arrays using pointers in c++: segmentation fault when accessing the returned array). Some people have been responding a bit negatively to my newb questions, so I went over my book about pointers, which did not help me much. So, here I go again.

In the previous question, I had a function void builder(int aSize1, int aSize2, int aSize3, int*** frequencies) that I thought would dynamically allocate memory for the 3d array passed in for the int*** frequencies parameter and initialize it. However, I was told that only a copy would be passed into the function and I would be allocating and initializing just for the copy not the original. Hence, they have advised me to use a reference instead, rendering the function prototype as void builder(int aSize1, int aSize2, int aSize3, int***& frequencies).

However, I recalled that just yesterday when I first stumbled upon this concept of pass by reference using pointers, one would be able to manipulate the data of the pointer as well. To wit,

void change_what_this_points_to( int* a )
{
    *a = 42;
}

this function does change the value of a pointer that is fed into the function.

So, my question is, why does the former pass in a copy while the latter passes the real deal? I do not see much difference between the two functions, aside from the fact that one has more asterisks.

Any help would be appreciated. Thanks!

Upvotes: 0

Views: 80

Answers (2)

Dave
Dave

Reputation: 144

While the other answer says it perfectly I just thought I'd add my two cents just in case it helps. Think of a pointer as just an address in memory. You pass that address into a function, and the function writes something in there. Then after the function is called you can look in that same location in memory and see what value is there.

So let's assume you have the following code:

void SetValue(int *a){ *a = 10;}
void DoWork()
{
    int a; 
    SetValue(&a); 
}

The SetValue function takes as a parameter a pointer to an int, or as we'll think of it, an address in memory where an int is stored. The function then simply writes the number 10 to the passed in address.

The method DoWork then creates the memory for an int and passes the address of that memory to the function. So by the time DoWork returns the memory where "a" is stored has the value 10. Sounds like you have this already from your question but wanted to start here just in case.

Now let's pretend you want a function to allocate memory for you. What you are really asking the function to do is to allocate memory and tell me where that memory is. So you could do that with a pointer return value, i.e.

int* AllocateMemoryForMe()
{
    return new int(); //Creates memory for an int, let's pretend it's at location 0x100
}
void DoWork()
{
    int* a = NULL; // a has a value of 0x00
    a = AllocateMemoryForMe(); //a will now have the value of 0x100
    *a = 10; //We now write 10 to memory location 0x100
}

Or you could do this using a pointer. If you do this, what you actually have to do is pass into the function a location in memory to write the address of the allocated memory into, so a pointer to a pointer. So when the function returns you can look into this address and see what the address of newly created memory is. So for example:

void AllocateMemoryForMe(int** x)
{
    *x = new int(); //allocates memory for an int, let's pretend it's at memory location 0x200
}
void DoWork()
{
    int** a = new int*(); //Creates memory for an int pointer. Let's pretend it allocates memory at location 0x100. 
    AllocateMemoryForMe(a); //pass memory location 0x100 to the function.
    //Right now the address of a is still 0x100 but the data at the memory location is 0x200. This is the address of the int we want to write to.
    **a = 10; //This will now write 10 to the memory location allocated by the AllocateMemoryForMe() function. 

}

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 311058

This function

void change_what_this_points_to( int* a )
{
    *a = 42;
}

does not change the pointer itself. It changes the integer object pointed to by the pointer.

If you want to change the pointer itself you should write the function either the following way

void change_what_this_points_to( int * &a )
{
    a = new int( 42 );
}

or the following way

void change_what_this_points_to( int **a )
{
    *a = new int( 42 );
}

Thus returning to your function you should declare it either like

void builder(int aSize1, int aSize2, int aSize3, int*** &frequencies);

or like

void builder(int aSize1, int aSize2, int aSize3, int**** frequencies);

Upvotes: 1

Related Questions