Returning a reference? Why?

This is a discussion on Returning a reference? Why? within the C++ Programming forums, part of the General Programming Boards category; Taken from cplusplus.com tutorial: Code: CVector& CVector::operator= (const CVector& param) { x=param.x; y=param.y; return *this; } My question is: why ...

  1. #1
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64

    Returning a reference? Why?

    Taken from cplusplus.com tutorial:

    Code:
    CVector& CVector::operator= (const CVector& param)
    {
      x=param.x;
      y=param.y;
      return *this;
    }
    My question is: why do we return a CVector& and not just CVector? Could someone please explain it to me in detail?
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,662
    Consider what happens in operator chaining:
    Code:
    a = b = c;
    If the copy assignment operator returns a copy, then (b = c) would generate a copy which would then be assigned to a, resulting in a total of three copies. This is unnecessary work. By returning a (const) reference, on the other hand, only two copies are made.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    Code:
    a = b = c;
    This may sound silly, but is this equivalent to:

    Code:
    b = c;
    a = b;
    Or:

    Code:
    b = c;
    a = c;
    If it's the latter, then what you say makes sense. If it's the former, then I'm still a little bit puzzled.
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Mr_Miguel View Post
    Code:
    a = b = c;
    This may sound silly, but is this equivalent to:
    Code:
    a = b = c;  // is equivalent to 
    a = (b = c); // is equivalent to (functionally, at least):
    b = c;
    a = b;
    This is most useful in statements such as:
    Code:
    a = b = c = d = 0;
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    Well then... Let's assume that's true. Let's also assume for a moment that the operator = returns CVector. Then:

    Code:
    CVector c;
    b = c; //b is now a copy of CVector c;
    a = b; //a is now a copy of CVector b;
    
    //We now have three copies: one at c, one at b, one at a.
    Right? Now let's go back to reality. It returns a CVector&. Then:

    Code:
    CVector c;
    b = c; //b is now a copy of CVector c;
    a = b; //a is now a copy of CVector c;
    Is that what it means? That, when returning a reference, a becomes the same copy as b?
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Mr_Miguel View Post
    Well then... Let's assume that's true. Let's also assume for a moment that the operator = returns CVector. Then:

    Code:
    CVector c;
    b = c; //b is now a copy of CVector c;
    a = b; //a is now a copy of CVector b;
    
    //We now have three copies: one at c, one at b, one at a.
    Right? Now let's go back to reality. It returns a CVector&. Then:

    Code:
    CVector c;
    b = c; //b is now a copy of CVector c;
    a = b; //a is now a copy of CVector c;
    Is that what it means? That, when returning a reference, a becomes the same copy as b?
    No, they are distinct copies. The operator= makes sure of that. It's just that if you have

    Code:
    CVector CVector::operator= (const CVector& param) ....
    then you also get the compiler to copy the *this when it is returned back to the calling code. Which is a bit unnecessary, as we are not going to modify the return value.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Well then... Let's assume that's true. Let's also assume for a moment that the operator = returns CVector. Then:

    Code:

    CVector c;
    b = c; //b is now a copy of CVector c;
    a = b; //a is now a copy of CVector b;

    //We now have three copies: one at c, one at b, one at a.
    If you do a = b = c and operator= returns a copy, you should get
    a) c is copied to b: assignment
    b) b is copied to pass to operator= of instant a: copy constructor
    c) copy of b is copied to a
    d) a is copied and returned but not used: copy constructor

    In code
    Code:
         CVector a, b, c;
         b = c;
         a = CVector(b);
         CVector(a);
    If you return a reference, calls to copy constructors won't happen.

    Hence, if you can return large objects as references (if the returned object is not local to the function), do so.
    Last edited by anon; 09-13-2007 at 10:16 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  8. #8
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    First lets make sure we're all on the same page...
    Code:
    CVector& CVector::operator= (const CVector& param)
    {
      x=param.x;
      y=param.y;
      return *this;
    }
    When you do: a = b; then b = param in the function above, and a = this.
    For a simple statement like that, you don't care about the return value since you're not assigning a to anything else; but in the following case:
    a = b = c;
    c = param & b = this, then the reference that is returned is sent to operator=() again, but this time the previous return value = param, and a = this.

    There's no point in creating a whole new object and returning it because in the first case nobody will use it anyways, and in the second case a reference will do just as well as a new object, but without the extra work required to create an object...

  9. #9
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    From http://www.codeproject.com/useritems...ces_in_c__.asp

    References are nothing but constant pointer in C++. A Statement int &i = j; will be converted by compiler to int *const i = &j; i.e References are nothing but constant pointers. They need initialization because constants must be initialized and since the pointer is constant they can't point to anything else. Lets take the same example of references in C++ and this time we will use the syntax what compiler uses when it sees references.
    That explains it. If a reference is just a constant pointer, then I understand why you say it's better to return a reference: pointers have tipically the size of 4 bytes (at least in 32-bit machines); objects themselves can be much larger than 4 bytes. Am I right?
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Mr_Miguel View Post
    From http://www.codeproject.com/useritems...ces_in_c__.asp



    That explains it. If a reference is just a constant pointer, then I understand why you say it's better to return a reference: pointers have tipically the size of 4 bytes (at least in 32-bit machines); objects themselves can be much larger than 4 bytes. Am I right?
    Yup, that's the point - references are smaller than most objects.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,662
    References are nothing but constant pointer in C++. A Statement int &i = j; will be converted by compiler to int *const i = &j; i.e References are nothing but constant pointers.
    In practice I believe this is true, but conceptually references are a little more than constant pointers. They are aliases of existing objects, and as such there are no null references, even though there can be null constant pointers.

    If a reference is just a constant pointer, then I understand why you say it's better to return a reference: pointers have tipically the size of 4 bytes (at least in 32-bit machines); objects themselves can be much larger than 4 bytes. Am I right?
    Yes.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Nov 2006
    Location
    Coimbra, Portugal
    Posts
    64
    http://www.parashift.com/c++-faq-lit...s.html#faq-8.1

    It seems a reference is implemented using the machine address of an object. A pointer also contains the address of an object, but it seems a reference isn't quite a pointer itself.

    Anyways, point taken. Thank you all for your help.
    Name: Miguel Martins
    Date of birth: 14th August 1987

    "He who hesitates is lost."

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Mr_Miguel View Post
    http://www.parashift.com/c++-faq-lit...s.html#faq-8.1

    It seems a reference is implemented using the machine address of an object. A pointer also contains the address of an object, but it seems a reference isn't quite a pointer itself.

    Anyways, point taken. Thank you all for your help.
    There is a difference in the MEANING (semantics) of a reference and a pointer [not to mention that the way you "access" a pointer vs. a reference is different], but the internal implementation is a pointer [at least in most architectures]. However, the fact that it's a pointer is "hidden" from the programmer in all aspects - the programmer just "knows" that it is "the same object as somewhere else".

    And the benefit of returning a reference vs. a copy of the object, the benefit is that a reference is the same size as a pointer, so the returned value is "short" relative to the whole object, and that is why it's used here.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. C OpenGL Compiler Error?
    By Matt3000 in forum C Programming
    Replies: 12
    Last Post: 07-07-2006, 04:42 PM
  5. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 09:18 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21