Topic: Call by reference using * and &


Author: lam@saifr00.cfsat.honeywell.com (Josh Lam)
Date: Mon, 13 Apr 92 21:43:11 GMT
Raw View
In C++, call by reference can be accomplished using pointers (like in C) or
by reference (&).  Question:  What are some advantages of using references
over pointers (or vice versa)

ie the following functions accomplish pretty much the same thing:

void func1(int & i)  // using the reference method
{
  ...
}

and

void func2(int * i)  // using pointer method
{
  ...
}


The couple of advantages (at least from my limited experiences with C++) of
using the reference method over the pointer method are:

1)  It provides a cleaner interface into the function, makes it a little
    easier to read and to use

2)  The programmer does not have to worry about the address of the pointer,
    makes it a little easier to program

Thus,

void func1(int & i)  // reference method
{
   ...

   i = 100;

   ...
}

is 'preferred' over

void func2(int * i)   // pointer method
{
  ...

  *i = 100;

  ...
}


What are some other advantages? Is one really often (if not
always) preferred over the other?

I appreciate any comments.  If this has already been discussed
in a separate subject, I apologise for repetition.

Thanks!

Josh Lam
Honeywell Inc
@cum-vax.honeywell.com:lam@saifr00.cfsat.honeywell.com

--
Josh Lam
Honeywell Inc
@cum-vax.honeywell.com:lam@saifr00.cfsat.honeywell.com





Author: dougm@cns.caltech.edu (Doug McNought)
Date: Tue, 14 Apr 1992 13:32:16 GMT
Raw View
In article <1992Apr13.214311.24013@saifr00.cfsat.honeywell.com> lam@saifr00.cfsat.honeywell.com (Josh Lam) writes:

   In C++, call by reference can be accomplished using pointers (like in C) or
   by reference (&).  Question:  What are some advantages of using references

 [deleted]

   The couple of advantages (at least from my limited experiences with C++) of
   using the reference method over the pointer method are:

   1)  It provides a cleaner interface into the function, makes it a little
       easier to read and to use

   2)  The programmer does not have to worry about the address of the pointer,
       makes it a little easier to program

Some people don't like using references for this purpose, since when reading
the code it is not immediately obvious from the form of the function call that
a variable might be changed by the function. With the address passed explicitly
it is clearer that this is a VAR parameter (as we ex-Pascal types say :). It's
a matter of taste--I don't think there are any real efficiency differences
between the two methods.

   Thus,

   void func1(int & i)  // reference method

   is 'preferred' over

   void func2(int * i)   // pointer method

   What are some other advantages? Is one really often (if not
   always) preferred over the other?

Stroustrup prefers passing an explicit pointer. I am ambivalent on this issue,
since my code (so far) is for myself alone, and, having used Pascal extensively
I am comfortable with the idea of pass-by-reference. Often it is clear from
context that a variable is being changed.

   I appreciate any comments.  If this has already been discussed
   in a separate subject, I apologise for repetition.

regards,
doug
--
<><><><><><><><><><><><><><><>Go Orioles<><><><><><><><><><><><><><><><>
<> Doug McNaught                          dougm@descartes.caltech.edu <>
<>  Help!!! I'm addicted to *Spaceward Ho!* Is there a support group? <>
<><><><><><><><><><><><><><><>Go Orioles<><><><><><><><><><><><><><><><>




Author: davisonj@en.ecn.purdue.edu (John M Davison)
Date: Tue, 14 Apr 92 13:57:17 GMT
Raw View
In article <DOUGM.92Apr14053216@bradbury.cns.caltech.edu> dougm@cns.caltech.edu (Doug McNought) writes:
>In article <1992Apr13.214311.24013@saifr00.cfsat.honeywell.com> lam@saifr00.cfsat.honeywell.com (Josh Lam) writes:
>   In C++, call by reference can be [faked] using pointers (like in C) or
>   by reference (&).  Question:  What are some advantages of using references

>Some people don't like using references for [deleted] purpose, since when
>reading
>the code it is not immediately obvious from the form of the function call that
>a variable might be changed by the function.

        Like when you pass an array in C?

> With the address passed explicitly
>it is clearer that this is a VAR parameter (as we ex-Pascal types say :).

        No, it isn't.  A responsible C++ programmer will make intelligent use
of the "const" keyword to distinguish between read-only and "write/modify"
access, e.g.

int foo(const thing &baz)     baz is read-only, passed by reference
int foo(thing &baz)           baz is writable, passed by reference

        A decent C programmer can do the following:

int foo(const thing *baz)     baz points to a read-only segment
int foo(thing *baz)           baz points to a writable segment

>Often it is clear from
>context that a variable is being changed.

        If isn't clear, you are probably doing something wrong.

davisonj@ecn.purdue.edu




Author: berczuk@world.std.com (Stephen P Berczuk)
Date: 14 Apr 92 14:08:11 GMT
Raw View
A couple of things to keep in mind:
1) Having a reference argument prevents you from having optional
   arguments or default values for user defined classes (at least for
   the moment..) for example you can have a function like:
      foo(myclass* xx=NULL){ if(xx=NULL) // use default values}
  but not... foo(myclass&=defaultValue);

2) In past work I have done it was generally considered good form to use
    reference args only when the arg is const so that there is NO confusion
   about whether the arg can be side-effected.  eg, foo(const aClass& x)
   not foo(aClass& x).  of course this is a matter of local convention,
   but is is probably safer to stick to using referneces as a means of
   saving object copies (without resorting to pointers, which muddy the
   syntax at times...)

I also seem to recall having conversations about virtual functions on derived
classed not working right w reference arguments, but I may be confusing this
with something else...

-steve berczuk
berczuk@world.std.com




Author: jak@cs.brown.edu (Jak Kirman)
Date: Tue, 14 Apr 1992 17:47:20 GMT
Raw View
In article <BMpB9o.rp@world.std.com> berczuk@world.std.com (Stephen P Berczuk) writes:
>   1) Having a reference argument prevents you from having optional
>      arguments or default values for user defined classes (at least for
>      the moment..) for example you can have a function like:
>         foo(myclass* xx=NULL){ if(xx=NULL) // use default values}
>     but not... foo(myclass&=defaultValue);

Indeed you can:

class MyClass { };

static MyClass fooDefault;

void foo (MyClass& a = fooDefault)
{
  if (&a == &fooDefault)
  {
    // default was used
  }
  // etc.
}

main ()
{
  MyClass x;
  foo ();
  foo (x);
}

This works on AT&T 3.0.1 and Sun 2.1.

There is some name-space pollution, of course; it would be nice if the
default argument could be a static member of the function...

>   2) In past work I have done it was generally considered good form to use
>       reference args only when the arg is const so that there is NO confusion
>      about whether the arg can be side-effected.  eg, foo(const aClass& x)
>      not foo(aClass& x).  of course this is a matter of local convention,
>      but is is probably safer to stick to using referneces as a means of
>      saving object copies (without resorting to pointers, which muddy the
>      syntax at times...)

On the whole I would agree, though obviously there are cases where
pointers are not an option, such as operators.  Also, there are cases
where the semantics are obvious, and pointers simply complicate things;
a trivial example of this is a swap function.

                         Jak Kirman                        jak@cs.brown.edu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
No matter how happily a woman may be married, it always pleases her to
discover that there is a nice man who wishes that she were not.
                                                             -- H.L. Mencken




Author: rmartin@willing.Rational.COM (Bob Martin)
Date: 15 Apr 92 00:06:01 GMT
Raw View
lam@saifr00.cfsat.honeywell.com (Josh Lam) writes:

>In C++, call by reference can be accomplished using pointers (like in C) or
>by reference (&).  Question:  What are some advantages of using references
>over pointers (or vice versa)

The form:

 void f(TYPE&);

is prefered over the form:

 void f(TYPE*);

There are several good reasons for this.  First, from the caller's
point of view there is no difference between

 void f(const TYPE&);

and

 void f(const TYPE);

Thus, the designer of the function can choose whether a call-by-value
or a call-by-reference paradigm is used.   Thus, if TYPE were a huge
structure, call by reference could be used to speed up the call.  If
TYPE were a primitive, or very small struct, pass by value might be
more appropriate.  The function designer can decide, and the client
never needs to know.

Secondly, the forms:

 void f(TYPE*);
 void f(TYPE&);

are not semantically equivalent.  They both represent the
pass-by-value paradigm, but the pointer form allows the argument to be
zero, whereas the reference form does not.  The reference form
*guarantees* that a real object is being refered to.

Both forms are useful, but should be used at the appropriate times.
When the pointer form is used, the called function should always
assume that the argument can be zero.  When using the reference form,
the called function should never check for zero.

--
+---Robert C. Martin---+-RRR---CCC-M-----M-| R.C.M. Consulting         |
| rmartin@rational.com |-R--R-C----M-M-M-M-| C++/C/Unix Engineering    |
|     (Uncle Bob.)     |-RRR--C----M--M--M-| OOA/OOD/OOP Training      |
+----------------------+-R--R--CCC-M-----M-| Product Design & Devel.   |




Author: mac@coos.dartmouth.edu (Alex Colvin)
Date: 15 Apr 92 12:27:37 GMT
Raw View
lam@saifr00.cfsat.honeywell.com (Josh Lam) writes:

>In C++, call by reference can be accomplished using pointers (like in C) or
>by reference (&).  Question:  What are some advantages of using references
>over pointers (or vice versa)

>Thus,
>void func1(int & i)  // reference method
>is 'preferred' over
>void func2(int * i)   // pointer method

One advantage of the older pointer method is that the caller makes it
explicit that the integer (*i) is subject to change.
References are handy for those cases where addresses are passed just
in order to avoid copying data
--
Alex Colvin
New England Digital
mac@cs.virginia.edu




Author: lewis@sophists.com (Lewis Pringle)
Date: Fri, 17 Apr 1992 05:30:53 GMT
Raw View
In article <BMpB9o.rp@world.std.com> berczuk@world.std.com (Stephen P Berczuk) writes:
>A couple of things to keep in mind:
>1) Having a reference argument prevents you from having optional
>   arguments or default values for user defined classes (at least for
>   the moment..) for example you can have a function like:
>      foo(myclass* xx=NULL){ if(xx=NULL) // use default values}
>  but not... foo(myclass&=defaultValue);
>
What is wrong with:
 void foo (myClass& arg = *0)
 {
  if (&arg == 0) {
   // use default value
  }
 }


--
Reading peoples .signatures is a real waste of time.

lewis@sophists.com                                           (Lewis G. Pringle)




Author: skochhar@cvbnet.prime.com (Sandeep Kochhar x4618 5-2)
Date: 20 Apr 92 15:57:14 GMT
Raw View
In article <1992Apr17.053053.10400@sophists.com>, lewis@sophists.com (Lewis Pringle) writes:
|> What is wrong with:
|>  void foo (myClass& arg = *0)
|>  {
|>   if (&arg == 0) {
|>    // use default value
|>   }
|>  }
|>

The above (passing *0) as a reference argument works on my Sun C++ 2.1
compiler.
However, I have a couple of questions:
    - Is the above legal according to C++ standards (ARM, ANSI, etc.) and
 not just a compiler quirk?
    - What does *0 conceptually mean?  In my code, when an
 argument is Foo&, I assume that I have an object of class Foo
 being passed in and thus avoid the test
  if (&arg == 0)
 Doesn't passing *0 imply that a valid Foo object should exist
 at address 0?

Thanks.




Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 20 Apr 92 20:45:23 GMT
Raw View

skochhar@cvbnet.prime.com (Sandeep Kochhar x4618 5-2 @ Computervision) writes

 > In article <1992Apr17.053053.10400@sophists.com>, lewis@sophists.com (Lewis Pringle) writes:
 > |> What is wrong with:
 > |>  void foo (myClass& arg = *0)
 > |>  {
 > |>   if (&arg == 0) {
 > |>    // use default value
 > |>   }
 > |>  }
 > |>
 >
 > The above (passing *0) as a reference argument works on my Sun C++ 2.1
 > compiler.

Very strange. Cfront 2.1 (on which Sun 2.1 is based) and 3.0 rejects it:

"", line 3: error: non pointer dereferenced

 > However, I have a couple of questions:
 >     - Is the above legal according to C++ standards (ARM, ANSI, etc.) and
no.

 >  not just a compiler quirk?
If that.

 >     - What does *0 conceptually mean?  In my code, when an
 >  argument is Foo&, I assume that I have an object of class Foo
 >  being passed in and thus avoid the test
 >   if (&arg == 0)
 >  Doesn't passing *0 imply that a valid Foo object should exist
 >  at address 0?
yes - and that wouldn't be a good idea, so it's illegal.




Author: berczuk@world.std.com (Stephen P Berczuk)
Date: Mon, 20 Apr 1992 21:51:25 GMT
Raw View
-------
The above (passing *0) as a reference argument works on my Sun C++ 2.1
compiler.
However, I have a couple of questions:
    - Is the above legal according to C++ standards (ARM, ANSI, etc.) and
        not just a compiler quirk?
    - What does *0 conceptually mean?  In my code, when an
        argument is Foo&, I assume that I have an object of class Foo
        being passed in and thus avoid the test
                if (&arg == 0)
        Doesn't passing *0 imply that a valid Foo object should exist
        at address 0?
----
let me clarify a point about my orignial post..
when I said that the reference form prevents passing default args I was
thinking more along the lines of temporary >>OBJECTS<<. having a null
pointer makes sense sometimes in the sense of "if we have been passed
an allocated object, use it, otherwise do a default, or allocate a new
object"

by passing default object arguments I was thinking more along the lines
of foo(int& x=23){//...}
what I have often felt a need to do was have a function declaration of the
form foo(myClass& x= myClass(//stuff). now I realise that that syntax doesn't
work even if you have non reference arguments, but since the question addresses
the difference between reference and pointer arguments I suggested that
in situations where there is some default behaviour required if an arg is not
passed that the pointer syntax is preferable..

while you can say foo(myClass& x=*NULL), I donlt think it has much meaning
and will probably cause more confusion than doing pointer dereferencing.
steve berczuk
berczuk@world.std.com




Author: jimad@microsoft.com (Jim ADCOCK)
Date: 22 Apr 92 22:22:31 GMT
Raw View
In article <3067@cvbnetPrime.COM> skochhar@cvbnet.prime.com (Sandeep Kochhar x4618 5-2) writes:
|In article <1992Apr17.053053.10400@sophists.com>, lewis@sophists.com (Lewis Pringle) writes:
||> What is wrong with:
||>  void foo (myClass& arg = *0)
||>  {
||>   if (&arg == 0) {
||>    // use default value
||>   }
||>  }
||>
|
|The above (passing *0) as a reference argument works on my Sun C++ 2.1
|compiler.
|However, I have a couple of questions:
|    - Is the above legal according to C++ standards (ARM, ANSI, etc.) and
| not just a compiler quirk?

The above is not legal according to the working position of the ANSI-C++
committee.  Strict "legality" on this issue is not established until
the ANSI-C++ standard goes through final vote some indefinite time in
the future.

Also, not yet clearly established is what "constraints" C++ compilers
have when presented with one or another "illegal" construct such as the above.
One possibility is that this, that or another could be labeled "unconstrained
errors."  An "unconstrained error" represents something that programmers
are not suppose to do, but which compiler are allowed to take any action
to when presented with the problem.  I suspect that C++ compilers today
and in the future will take some ill-defined combination of the following
actions, depending on the exact schenerio where the null reference occurs:

* generate "correct" code and/or
* generate "incorrect" code and/or
* issue an error and/or
* issue a warning and/or
* cause a runtime trap and/or
* cause a runtime error and/or
....

|    - What does *0 conceptually mean?

Conceptually it means that the programmer has made an error.

In my code, when an
| argument is Foo&, I assume that I have an object of class Foo
| being passed in and thus avoid the test
|  if (&arg == 0)

I agree with your programming convention.

| Doesn't passing *0 imply that a valid Foo object should exist
| at address 0?

No, it implies the programmer has written an illegal program.