Pass a pointer variable to a function accept reference

Discussion in 'C++' started by Louis, Sep 29, 2009.

  1. Louis

    Louis Guest

    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
     
    Louis, Sep 29, 2009
    #1
    1. Advertising

  2. Louis wrote:

    > 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
     
    Michael Tsang, Sep 29, 2009
    #2
    1. Advertising

  3. "Louis" <> writes:

    > 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 Bourguignon__
     
    Pascal J. Bourguignon, Sep 29, 2009
    #3
  4. Louis

    Paul N Guest

    On 29 Sep, 07:33, "Louis" <> wrote:

    >     temp+= temp + 2;


    Just a side point, but is this line doing what you think it does?
     
    Paul N, Sep 29, 2009
    #4
  5. Louis

    Louis Guest

    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" <>
    Newsgroups: comp.lang.c++
    Sent: Tuesday, September 29, 2009 7:01 PM
    Subject: Re: Pass a pointer variable to a function accept reference


    > "Louis" <> writes:
    >
    >> 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 Bourguignon__

    "Pascal J. Bourguignon" <> wrote in message
    news:...
    > "Louis" <> writes:
    >
    >> 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 Bourguignon__
     
    Louis, Sep 30, 2009
    #5
  6. Louis

    Louis Guest

    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" <> wrote in message
    news:h9sh9a$1f7$-september.org...
    > Louis wrote:
    >
    >> 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

    >
     
    Louis, Sep 30, 2009
    #6
  7. "Louis" <> writes:
    > 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);




    > > 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...?


    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).

    --
    __Pascal Bourguignon__
     
    Pascal J. Bourguignon, Sep 30, 2009
    #7
  8. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Louis wrote:

    > 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-----
     
    Michael Tsang, Oct 1, 2009
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr A
    Replies:
    111
    Views:
    2,149
  2. Robert
    Replies:
    10
    Views:
    1,381
    E. Robert Tisdale
    Aug 24, 2005
  3. LuB
    Replies:
    6
    Views:
    465
    Mike Wahler
    Sep 23, 2005
  4. Tricky
    Replies:
    0
    Views:
    591
    Tricky
    Mar 19, 2009
  5. Tricky
    Replies:
    0
    Views:
    1,028
    Tricky
    Mar 19, 2009
Loading...

Share This Page