Pass a pointer variable to a function accept reference

L

Louis

Hi all:

Im having a little bit confuse of passing a pointer variable to a function
that accept reference:

void test(int &temp)
{

temp+= temp + 2;

cout << "function:" << temp << endl;
cout << "function:" << &temp << endl; //c:0x22ff1c
}

int main(int argc, char *argv[])
{

int c = 0;
int *d = &c;
cout << "d:" << *d << endl;
test(*d); // i guess, *d is dereference of d, which is value of c, and
same as int &temp = c, like passing reference?
cout << "c:" << &c << endl; //function:0x22ff1c,
return 0;
}

it works, i guess, *d is dereference of d, which is value of c, and same as
int &temp = c, like passing reference?

In the above code i'm trying to pass a dereference pointer d, which is
contain value of c, can anyone can explain to me if this is a good way to
pass a pointer variable?

Many Thanks

L
 
M

Michael Tsang

Louis said:
Hi all:

Im having a little bit confuse of passing a pointer variable to a function
that accept reference:

void test(int &temp)
test is a void function accepting an int lvalue
{

temp+= temp + 2;

cout << "function:" << temp << endl;
cout << "function:" << &temp << endl; //c:0x22ff1c
}

int main(int argc, char *argv[])
{

int c = 0;
int *d = &c;
cout << "d:" << *d << endl;
*d is an int lvalue which is the same object as c
 
P

Pascal J. Bourguignon

Louis said:
Hi all:

Im having a little bit confuse of passing a pointer variable to a
function that accept reference:

void test(int &temp)
{

temp+= temp + 2;

cout << "function:" << temp << endl;
cout << "function:" << &temp << endl; //c:0x22ff1c
}

int main(int argc, char *argv[])
{

int c = 0;
int *d = &c;
cout << "d:" << *d << endl;
test(*d); // i guess, *d is dereference of d, which is value of c,
and same as int &temp = c, like passing reference?
cout << "c:" << &c << endl; //function:0x22ff1c,
return 0;
}

it works, i guess, *d is dereference of d, which is value of c, and
same as int &temp = c, like passing reference?


Perhaps you could get a hint from the character used to denote a reference: &

When you write: int &temp; temp = c; int x = temp;
what actually happen is like: int * temp; temp = &c; int x = *temp;

int x = *temp;
<=> int x = *&c; // since temp = &c
<=> int x = c; // since *& = identity.

You may consider the reference variables as pointers that are
automatically deferenced everytime they're used.

In the above code i'm trying to pass a dereference pointer d, which is
contain value of c, can anyone can explain to me if this is a good way
to pass a pointer variable?

You didn't pass a pointer, you passed an int.
To pass a pointer you'd have to use the *.


void take_a_raw_pointer (int* param){
(*param)=42; // modifies the int pointed to by param.
param=0; // modifies param.
}

void take_a_pointer_reference(int*& param){
(*param)=42; // modifies the int pointed to by the pointer referenced by param.
param=0; // modifies the pointer referenced by param.
}

/*
The difference is that take_a_raw_pointer will accept temporary
pointers returned by functions, while take_a_pointer_reference will
want a pointer variable.
*/

int* p=&c;
int* compute_some_int_pointer();

take_a_raw_pointer(&c);
take_a_raw_pointer(p); // p cannot be modified assert(p==&c);
take_a_raw_pointer(compute_some_int_pointer());

take_a_pointer_reference(p); // p might be modified and be null or point to another int than c.
 
L

Louis

Hi Pascal:

Thanks for you reply;

Few more question if you dont mind.

In my case passing pointer variable to function is the best using a pointer
reference or a raw pointer?

int test(int *&temp)
{
(*temp)++;
cout << *temp << endl;
}

int test(int *temp)
{
(*temp)++;
cout << *temp << endl;
}

\\main
int c = 1;
int *d = &c;
test(d);

and you mentioned
/*
The difference is that take_a_raw_pointer will accept temporary
pointers returned by functions, while take_a_pointer_reference will
want a pointer variable.
*/
still a bit confuse
do u mean using raw pointer, temp will modify the same address where d
pointing to?
while using pointer reference, temp will modify the reference of d...?

Thanks
L


----- Original Message -----
From: "Pascal J. Bourguignon" <[email protected]>
Newsgroups: comp.lang.c++
Sent: Tuesday, September 29, 2009 7:01 PM
Subject: Re: Pass a pointer variable to a function accept reference

Louis said:
Hi all:

Im having a little bit confuse of passing a pointer variable to a
function that accept reference:

void test(int &temp)
{

temp+= temp + 2;

cout << "function:" << temp << endl;
cout << "function:" << &temp << endl; //c:0x22ff1c
}

int main(int argc, char *argv[])
{

int c = 0;
int *d = &c;
cout << "d:" << *d << endl;
test(*d); // i guess, *d is dereference of d, which is value of c,
and same as int &temp = c, like passing reference?
cout << "c:" << &c << endl; //function:0x22ff1c,
return 0;
}

it works, i guess, *d is dereference of d, which is value of c, and
same as int &temp = c, like passing reference?


Perhaps you could get a hint from the character used to denote a
reference: &

When you write: int &temp; temp = c; int x =
temp;
what actually happen is like: int * temp; temp = &c; int x =
*temp;

int x = *temp;
<=> int x = *&c; // since temp = &c
<=> int x = c; // since *& = identity.

You may consider the reference variables as pointers that are
automatically deferenced everytime they're used.

In the above code i'm trying to pass a dereference pointer d, which is
contain value of c, can anyone can explain to me if this is a good way
to pass a pointer variable?

You didn't pass a pointer, you passed an int.
To pass a pointer you'd have to use the *.


void take_a_raw_pointer (int* param){
(*param)=42; // modifies the int pointed to by param.
param=0; // modifies param.
}

void take_a_pointer_reference(int*& param){
(*param)=42; // modifies the int pointed to by the pointer referenced
by param.
param=0; // modifies the pointer referenced by param.
}

/*
The difference is that take_a_raw_pointer will accept temporary
pointers returned by functions, while take_a_pointer_reference will
want a pointer variable.
*/

int* p=&c;
int* compute_some_int_pointer();

take_a_raw_pointer(&c);
take_a_raw_pointer(p); // p cannot be modified assert(p==&c);
take_a_raw_pointer(compute_some_int_pointer());

take_a_pointer_reference(p); // p might be modified and be null or point
to another int than c.
Pascal J. Bourguignon said:
Louis said:
Hi all:

Im having a little bit confuse of passing a pointer variable to a
function that accept reference:

void test(int &temp)
{

temp+= temp + 2;

cout << "function:" << temp << endl;
cout << "function:" << &temp << endl; //c:0x22ff1c
}

int main(int argc, char *argv[])
{

int c = 0;
int *d = &c;
cout << "d:" << *d << endl;
test(*d); // i guess, *d is dereference of d, which is value of c,
and same as int &temp = c, like passing reference?
cout << "c:" << &c << endl; //function:0x22ff1c,
return 0;
}

it works, i guess, *d is dereference of d, which is value of c, and
same as int &temp = c, like passing reference?


Perhaps you could get a hint from the character used to denote a
reference: &

When you write: int &temp; temp = c; int x =
temp;
what actually happen is like: int * temp; temp = &c; int x =
*temp;

int x = *temp;
<=> int x = *&c; // since temp = &c
<=> int x = c; // since *& = identity.

You may consider the reference variables as pointers that are
automatically deferenced everytime they're used.

In the above code i'm trying to pass a dereference pointer d, which is
contain value of c, can anyone can explain to me if this is a good way
to pass a pointer variable?

You didn't pass a pointer, you passed an int.
To pass a pointer you'd have to use the *.


void take_a_raw_pointer (int* param){
(*param)=42; // modifies the int pointed to by param.
param=0; // modifies param.
}

void take_a_pointer_reference(int*& param){
(*param)=42; // modifies the int pointed to by the pointer referenced
by param.
param=0; // modifies the pointer referenced by param.
}

/*
The difference is that take_a_raw_pointer will accept temporary
pointers returned by functions, while take_a_pointer_reference will
want a pointer variable.
*/

int* p=&c;
int* compute_some_int_pointer();

take_a_raw_pointer(&c);
take_a_raw_pointer(p); // p cannot be modified assert(p==&c);
take_a_raw_pointer(compute_some_int_pointer());

take_a_pointer_reference(p); // p might be modified and be null or point
to another int than c.
 
L

Louis

Hi Michael:

1. test is a void function accepting an int lvalue
2. c is passed into test

Is that means i'm passing an int c, and temp is reference to c , eq int
&temp = c.

Let say for some reason, i must use pointer in main
int *ptr = new int(10);

and another function must accept an reference like void test(int &temp)

so passing ptr to test by using

test(*ptr);

will result passing as reference? is there any better way to do it? or this
is normal?

Many Thanks
L

Michael Tsang said:
Louis said:
Hi all:

Im having a little bit confuse of passing a pointer variable to a
function
that accept reference:

void test(int &temp)
test is a void function accepting an int lvalue
{

temp+= temp + 2;

cout << "function:" << temp << endl;
cout << "function:" << &temp << endl; //c:0x22ff1c
}

int main(int argc, char *argv[])
{

int c = 0;
int *d = &c;
cout << "d:" << *d << endl;
*d is an int lvalue which is the same object as c
test(*d); // i guess, *d is dereference of d, which is value of c, c is passed into test
and
same as int &temp = c, like passing reference?
cout << "c:" << &c << endl; //function:0x22ff1c,
return 0;
}

it works, i guess, *d is dereference of d, which is value of c, and same
as int &temp = c, like passing reference?

In the above code i'm trying to pass a dereference pointer d, which is
contain value of c, can anyone can explain to me if this is a good way to
pass a pointer variable?

Many Thanks

L
 
P

Pascal J. Bourguignon

Louis said:
In my case passing pointer variable to function is the best using a
pointer reference or a raw pointer?

It depends.

You seen, pointers and references are low level constructs.

There are several different parameter passing modes, that can be
explained in a higher level way:

- input parameters: The argument may be an expression (r-value).

Assigning to the parameter, inside the function,
has only a local effect, the value of the
expression cannot be changed.


- output parameters: The argument cannot be an expression (r-value),
only a place (l-value). The old value in that
place is not used, the function stores a new
value there.

Assigning to the parameter, inside the function,
will change the value of the argument place.


- inout parameters: The argument cannot be an expression (r-value),
only a place (l-value). The old value is used by
the function, and may be modified by the
function.

Assigning to the parameter, inside the function,
will change the value of the argument place.


When programming, you should first be concerned only by these
considerations.



Then, there are different mechanisms by which these parameter passing
modes may be implemented:

- argument passing by copy: the data is copied from the argument
to the parameter (input), or from the
parameter to the argument (output).

- argument passing by reference: a pointer to the data is copied from
the argument to the parameter
(input); the argument data is
accessed by dereferencing the pointer
parameter, and can thus be modified
(output).

- argument passing by name: this is a complex parameter passing
mechanisms that was used in some
early languages such as
Algol. Basically, the name of the
argument variable was in some way
passed to the parameter, and then
when using the parameter, it would
find the place by indexing the name
in the symbol table.

- etc.


In the case of C, the only mechanism is argument passing by copy. All
the arguments are expressions that are evaluated and whose value is
copied to the parameter.

Implementing an input parameter is therefore straigtforward, it's what
is normally done.

(CI)
void f(int inputParameter){ assert(inputParameter==42); inputParameter=0; }
f(24*2);
int i=42; f(i); assert(i==42);
int a[]={3,42,3}; f(a[1]); assert(a[1]==42);


To implement an inout parameter, we must use a pointer to the place:

C(IO)
void f(int* inoutParameter){ assert((*inoutParameter)==42); (*inputParameter)=0; }
f(&(24*2)); // ERROR! we cannot take a pointer of an expression.
int i=42; f(&(i)); assert(i==0);
int a[]={3,42,3}; f(&(a[1])); assert(a[1]==0);


To implement an output parameter, we must use a pointer to the place,
just like for an inout parameter, but we do not read the value of the
place in the function, before setting it:

C(O)
void f(int* outputParameter){ (*outputParameter)=0; }
f(&(24*2)); // ERROR! we cannot take a pointer of an expression.
int i; f(&(i)); assert(i==0);
int a[3]; f(&(a[1])); assert(a[1]==0);



However, in C there is a strange treatment of arrays: they're
considered as pointer to the first element when passed as arguments.
And old versions of the language could not copy structure arguments
(at least beyond a certain size) either. Also, considerations of
performance will make you seek another mechanism to pass big arguments.

For these cases, an input parameter can still be passed using a pointer:

void f(const int* inputParameter,int size){
if(1<size){
process(inputParameter[1]);
}
}

In modern C can also be written as:

void f(const int inputParameter[],int size){
if(1<size){
process(inputParameter[1]);
}
}

int a[]={1,2,3}; f(a,sizeof(a)/sizeof(a[0]));
/* equivalent to: */ f(&(a[0]),sizeof(a)/sizeof(a[0]));


For an inout or output array parameter, we would just drop the 'const'.





Now, in C++ we have in addition the references, and argument passing
by reference. We can use it to implement inout and output parameters:

Implementing an input parameter is the same as in C:

C++(I)
void f(int inputParameter){ assert(inputParameter==42); inputParameter=0; }
f(24*2);
int i=42; f(i); assert(i==42);
int a[]={3,42,3}; f(a[1]); assert(a[1]==42);


To implement an inout parameter, we may use a reference to the place:

C++(IO)
void f(int& inoutParameter){ assert(inoutParameter==42); inputParameter=0; }
f(24*2); // ERROR! we cannot take a refernece of an expression.
int i=42; f(i); assert(i==0);
int a[]={3,42,3}; f(a[1]); assert(a[1]==0);


To implement an output parameter, we must use a pointer to the place,
just like for an inout parameter, but we do not read the value of the
place in the function, before setting it:

C++(O)
void f(int& outputParameter){ outputParameter=0; }
f(24*2); // ERROR! we cannot take a pointer of an expression.
int i; f(i); assert(i==0);
int a[3]; f(a[1]); assert(a[1]==0);


In C++, we still have the same problem with array, that are passed by
copy of a pointer to the first element by default, but we can now use
passing by reference:


typedef int Vector[3];
void f(const vector& inputParameter){
assert(inputParameter[1]==2);
inputParameter[1]=0;
}

int a[]={1,2,3}; f(a); assert(a[1]==0);

(and drop 'const' for inout and output parameters).


For structures there's no more size restriction for passing by copy,
but you might still want to use a reference there, to avoid copying
big structures.

In the case of a structure such as std::vector<int>, you may pass it
by copy, since it's really a small structure (usually 3 words), and
passing this structure by copy won't copy the elements in the vector.



A last word, compare the call sites in C++(I) and C++(IO) above:

int i=42; f(i); assert(i==42);
int i=42; f(i); assert(i==0);


It may look surprizing that in one case i is not changed (and couldn't
be changed), while in the other case, i can be changed. When reading
the call site alone, no syntax clues us about this difference. For
this reason, some C++ programmers prefer to keep using pointers for
inout and output parameters, see C(IO):

int i=42; f(&(i)); assert(i==0);



My own point of view is that (1) the name of the function should clue
you:

int salary=42; setSalary(salary); assert(salary==42);
int taxes; getTaxes(taxes); assert(taxes==0);

so that you can still use references, without any loss of readability,
and (2) you should avoid using inout and output parameters anyways,
and rather use a functional programming style, where you have only
input parameter and use results:

int salary=42; setSalary(salary); assert(salary==42);
int taxes; taxes=getTaxes(); assert(taxes==0);



In my case passing pointer variable to function is the best using a
pointer reference or a raw pointer?

So to answer your questions, it depends on whether the parameter is an
input, inout or output parameter. A pointer is small (one word), so
as an input parameter you can pass it by copy:

typedef int* intp;
void f(intp inputParameter);
int i=42; f(&i);
intp p=&i; f(p); assert(p==&i);

In the case of an inout or output parameter, if you choose to have a
call place hint that your pointer may be modified, you'd use a pointer
to the pointer:

typedef int* intp;
int k=24;
void f(intp* outputParameter){ (*outputParameter)=&k; }
intp p=0; f(&p); assert(p==&k);

If you choose better function names, you can use a reference:

typedef int* intp;
int k=24;
void getPointerToIntStorage(intp& outputParameter){ outputParameter=&k; }
intp p=0; getPointerToIntStorage(p); assert(p==&k);



still a bit confuse
do u mean using raw pointer, temp will modify the same address where d
pointing to?
while using pointer reference, temp will modify the reference of d...?

What I mean here is that take_a_raw_pointer takes a r-value
(expressions), while take_a_pointer_reference takes a l-value
(places).
 
M

Michael Tsang

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi Michael:

1. test is a void function accepting an int lvalue
2. c is passed into test

Is that means i'm passing an int c, and temp is reference to c , eq int
&temp = c. That is, &temp = &c

Let say for some reason, i must use pointer in main
int *ptr = new int(10);

and another function must accept an reference like void test(int &temp)

so passing ptr to test by using

test(*ptr);

will result passing as reference? is there any better way to do it? or
this is normal?
Dereferencing a pointer gets a l-value (reference), it will result passing
as reference
Many Thanks
L
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkrEQAQACgkQG6NzcAXitM+YIgCglTs13G/xVu0kqnMHM7ubLVGg
iWMAn3aHniSgD3/4nASg2Kgiv4UzGD3Z
=SMoQ
-----END PGP SIGNATURE-----
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,734
Latest member
manin

Latest Threads

Top