Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Call by reference

  1. Jul 13, 2009 #1
    I am confused by two versions of call by reference in C++. As an example two methods that square an integer (CBR stands for Call By Reference):

    Code (Text):
    //Version 1
    void squareCBR(int& x)
    {
         x = x * x;
    }

    //Version 2
    void squareCBR2(int* x)
    {
         (*x) = (*x) * (*x);
    }
     
    Let's call the functions:

    Code (Text):
    int x = 3;
    squareCBR(x);
    squareCBR2(&x);
     
    1) What I don't understand is that I'm calling squareCBR(int& a)
    by writing squareCBR(a). Why just a? I thought I'd have to pass an address to the function since the argument is (int& a).

    2) The same question about squareCBR2(int* x). I call this function by writing squareCBR2(&x). Why &x? I thought I'd have to pass a pointer since the argument is (int* x).
     
    Last edited: Jul 13, 2009
  2. jcsd
  3. Jul 13, 2009 #2
    &a is the address-of operator, and it returns a pointer to a.

    If "a" has type "int" then "&a" has type "int*", like this

    Code (Text):

    int a; //new variable a
    int *x = &a; //x is a pointer to a
     
    *x is the dereference operator, and returns the value pointed to by the pointer x. If "x" has type "int*" then "*x" has type "int", like this

    Code (Text):

    int b = *x; //b is a new variable assigned value pointed to by x (ie, a)
     
    When you pass an argument as a copy, it looks like this:

    Code (Text):

    int funcByCopy(MyClass x)
    {
       //stuff
    }
     
    and it is called like this:

    Code (Text):

    MyClass x;
    funcByCopy(x);
     
    This is inefficient because the MyClass object must be copied onto the stack. It would be more efficient to only pass the address of the object (pass by pointer), like this:

    Code (Text):

    int funcByPointer(MyClass *x)
    {
       //stuff
    }

    MyClass x;
    funcByPointer(&x);
     
    However some people find it confusing to have to deal with memory addresses directly, because an address might point to nothing at all..which would cause compilation errors. References are a way of telling the computer to use pointers without making the programmer have to think so much about safety. Using references, it can be done like this:

    Code (Text):

    int funcByReference(MyClass &x)
    {
      //stuff

    MyClass x;
    funcByReference(x);
     
    Notice that using references, the code can be written almost exacty the same way as with pass by copy, except that the compiler uses pointers under the hood for increased efficiency.
     
    Last edited: Jul 13, 2009
  4. Jul 14, 2009 #3

    jtbell

    User Avatar

    Staff: Mentor

    In C++, a reference parameter in a function, as in "void squareCBR(int& x), has the semantics of an alias (alternate name) for the argument in the function call, e.g. "squareCBR(a)". As junglebeast notes, the compiler usually implements a reference by using a "hidden" pointer.

    A significant practical difference between a reference and a pointer is that whereas you can change what a pointer points to, e.g.

    Code (Text):

    int a = 5;
    int b = 10;
    int *p = &a;
    cout << "p points to " << *p << endl;  // should display "p points to 5"
    p = &b;
    cout << "p points to " << *p << endl;  // should display "p points to 10"
     
    you cannot change what a reference points to, in a similar fashion.
     
  5. Jul 14, 2009 #4
    Dear junglebeast and jtbell,

    thanks for your help! It has become very clear to me now.
    I'd still like to mention why I didn't understand call by reference:

    1) I didn't know what a reference is, e.g.
    Code (Text):
    int x = 12;
    int& otherNameForX = x;
    otherNameForX = 24;     // The value of x is also changed to 24
    As jtbell mentions, otherNameForX is just an alias for x.

    2) The different uses of & :
    Code (Text):
    int x = 12;
    int* pointerToX = &x    // <--- &x is an address;
    int& otherNameForX =x;  // <---- int& stands for a reference
    I've thought about & only in the context of addresses.

    3) I realized what a function actually does. For example:
    Code (Text):

    void funcPointer(int* p){
          *p = *p + 2;
    }

    int main(){

        int x = 12;
        funcPointer(&x);

    return 0;
    }
    is equivalent to

    Code (Text):
    int main(){

        int x=12;
       
        int* p = &x;
        *p = *p + 2;

    return 0;
    }
     
    In short: What I realized, thanks also to junglebeast, is the following:
    When passing an address &x to funcPointer(int* p) the following assignment happens:
    funcPointer(int* p = &x).

    The same goes for funcRef(int& alias). When passing x to the function the following assignment happens: funcRef(int& alias = x).

    Realizing that this assignment occurs I can now understand what kind of "thing" I have to pass to the functions (either &x or x).

    Correct me if this is wrong.
     
    Last edited: Jul 14, 2009
  6. Jul 14, 2009 #5

    mgb_phys

    User Avatar
    Science Advisor
    Homework Helper

    Yes references are just a way of hiding the pointer.
    Also references are disliked by a lot of programmers because they don't look like pointers.

    So "function(int*x)" is clear that it is passing an int that is likely to be changed, while "function(int& x)" looks like it is just passing an int but could be changing it.
    Some common (although not universal) advice is to only pass const references.

    So "function(foo *_foo)" would be called with function(&_foo) making it clear that you are changing _foo while "function(foo& _foo)" called with function(_foo) doesn't change anything.
     
  7. Jul 14, 2009 #6

    jtbell

    User Avatar

    Staff: Mentor

    In my experience, programmers who first learned pointers (in C or some other language) tend to dislike references, whereas programmers who first learned references (e.g. in Fortran or Pascal) tend to dislike pointers. :smile:

    I first learned to program in Fortran many years ago, when arguments to Fortran subprograms and functions were always passed by reference, and pointers did not exist in the language. Therefore C++ references feel "natural" to me.
     
  8. Jul 15, 2009 #7

    rcgldr

    User Avatar
    Homework Helper

    Stuff like this was always fun to do in early versions of Fortran:

    Code (Text):

          call settotwo(1.0)
          a = 1.0
    c     a ends up == 2.0
          end

          subroutine settotwo(x)
          x = 2.0
          return
          end
     
    some compilers treated (0) as a pointer, initializing x(0) to point to &x(1)

    Code (Text):

          integer pointer(1)
          integer array(10)

    c     set pointer to array
    c     after this, pointer(1) == array(1), access to pointer(1) is forever lost
          pointer[0] = array[0]

    c     set pointer to absolute value (was used to access os system globals)
          pointer[0] = 32
     
     
    Last edited: Jul 15, 2009
  9. Jul 17, 2009 #8
    Thank mgb_phys. You explained very well the "danger" of using references.
     
  10. Jul 17, 2009 #9

    jtbell

    User Avatar

    Staff: Mentor

    By the way, the "references versus pointers" argument is an old and common one among C++ programmers. Try a Google search on something like "references versus pointers in C++" and you'll get many points of view. :smile:
     
  11. Jul 17, 2009 #10

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Not quite. For one thing, you can't change a reference. A reference someType & foo is similar to someType * const foo. Note that I said similar to, not equivalent to. There is no such thing as a null reference.

    e.g., google: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Reference_Arguments#Reference_Arguments [Broken]

    I disagree with this rule. As mentioned above, there is no such thing as a null reference. This alone is, IMHO, a reason to prefer references over pointers. A defensive programmer will check that a pointer passed as an argument is not null prior to referencing the pointer. This opens several cans of worms. What to do if it is null? Do you throw an exception, abort, return an error code? Whatever the case, the use of a pointer as opposed to a reference has made the job of documentation a bit harder, possibly considerably so, and has added the need for a new test case to achieve 100% code coverage.

    My projects do offer an out to the above: In the function's documented assumptions and limitations, specify that pointers are assumed to be valid (non-null). This is not a preferred usage of the assumptions and limitations; it usually becomes software ticket. Assumptions are intended to address physical assumptions like bodies are rigid, slow mass depletion doesn't affect dynamics, etc.

    Our rule is to disallow pass by reference for primitive types but to prefer pass by reference for structured types.
     
    Last edited by a moderator: May 4, 2017
  12. Jul 17, 2009 #11

    mgb_phys

    User Avatar
    Science Advisor
    Homework Helper

    That can also be a problem.
    If you want the pointer to be null to say that the function allocates the memory or you want a default value for an unused parameter you need to have some field inside the referenced object marking if it is valid or not which breaks RAII
     
  13. Jul 17, 2009 #12

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    I agree. References cannot be used if the thing being pointed to legitimately can be nothing, is not known at the time the variable is instantiated, if the pointer itself can change, and I am sure there are other places where references just won't work. You have to use pointers in such cases, and that means you have to be a bit more careful.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Call by reference
  1. Undefined Reference (Replies: 10)

  2. Fortran Call Question (Replies: 11)

Loading...