13

I don't understand why passing a pointer to a function doesn't change the data being passed in. If the function proto looked like this:

void func( int *p ); 

and func allocated memory to p, why can't it be used outside of the function? I thought that pointers were addresses?

ThomasMcLeod
  • 7,026
  • 4
  • 37
  • 71
TheFuzz
  • 2,487
  • 5
  • 27
  • 46

5 Answers5

18

Whilst something like this does what you expect:

void func(int *p)
{
    *p = 1;
}

int a = 2;
func(&a);
// a is now 1

this does not

void func(int *p)
{
    p = new int;
}

int *p = NULL;
func(p);
// p is still NULL

In both cases, the function works with a copy of the original pointer. The difference is that in the first example, you're trying to manipulate the underlying integer, which works because you have its address. In the second example, you're manipulating the pointer directly, and these changes only apply to the copy.

There are various solutions to this; it depends on what you want to do.

Oliver Charlesworth
  • 252,669
  • 29
  • 530
  • 650
  • so is is better to make a function prototype like this: func( int **p ); OR func( int *&p ); ? is there any real important differences ? – TheFuzz Jan 26 '11 at 03:09
  • 1
    @TheFuzz: This is just my personal opinion, and others may disagree strongly, so take it with a pinch of salt: I tend to only use references only where they're strictly necessary, e.g. in operator overloads and so on. In other locations, they can cause confusion (because just by looking at a function call, you can't tell whether it's pass-by-ref or pass-by-value), and they're more limited than pointers (can't be NULL, can't be re-seated). – Oliver Charlesworth Jan 26 '11 at 09:37
5

Arguments in C and C++ are passed by value. That means if type of the argument is a pointer to int, then the function receives a copy of the actual pointer argument, while still being able to change the int being pointed to.

Nikolai Fetissov
  • 77,392
  • 11
  • 105
  • 164
  • Arguments in C++ are passed by value... except if you pass by reference ;) – fredoverflow Jan 23 '11 at 19:57
  • 4
    @FredOverflow in which case the reference is passed by value, right? – San Jacinto Jan 23 '11 at 20:01
  • 1
    @San: No, because references are neither objects nor values. Technically speaking, you cannot pass them at all :) References are very special in C++. There is no such thing as "the value" of a reference, you can't have references to references etc. – fredoverflow Jan 23 '11 at 20:30
  • @FredOverflow Fair enough; I was just being goofy. You can, however, argue semantics all day. Pointers are neither objects nore values. However, a pointer can _point_ to an object and contains a _value_ which represents the address of the oject. In much the same way, a reference can be thought of as containing a value (probably implemented as an address); it's just a value that has different rules such that you can't modify or read the address. When you pass something by reference, if there are no values exchanged, how does a function know what object you are "referring" to? – San Jacinto Jan 23 '11 at 20:41
4

It's really hard to say, what you're asking..

My guess - you can change the memory, that is pointed by the pointer p, but you can't "redirect" or delete the pointer (or allocate memory )? If so, pass you pointer as reference:
void func( int &*p )
Or as double pointer
void func( int **p )
to be able to change it (i'm talking about the pointer)

Kiril Kirov
  • 35,473
  • 22
  • 102
  • 177
4

Pointers are addresses. If you pass a pointer into a function, the function can then modify data created outside the scope of the function. However, if you want to allocate memory inside a function for use outside the function, you need to pass in a double pointer. The reason is that pointers are passed by value, and the allocation assigns a new value to the pointer for the newly allocated block. But that new value is lost when the function returns. But you can use this method to do what you need:

void func(int * * pp)
{
    * pp = new int;
}

use the func thus:

int * myPointer;
func(& myPointer);
// do stuff with myPointer
delete myPointer;
ThomasMcLeod
  • 7,026
  • 4
  • 37
  • 71
1

I wouldn't agree to Nikolai's answer. In C++ there are two ways of passing the arguments.

f(Type Name)

is your case, where Type is int* and Name is p (note that int *p actually means int* p). In this case, inside your function Name is a copy of the object that you pass to the function.

The second way

f(Type & Name)

does not make a copy, but creates an alias to the object instead, so that you can modify the original object.

In your case, the object is the pointer of a type int*. As you pass it using the first syntax, you get a copy of it which you modify and the original pointer is left unchanged. If you want to change the original pointer, then you should pass it by reference, so for Type=int* and Name=p you'd get

f(int*& p)
Roman L
  • 2,896
  • 22
  • 37