passing object by reference in C++

220,024

Solution 1

What seems to be confusing you is the fact that functions that are declared to be pass-by-reference (using the &) aren't called using actual addresses, i.e. &a.

The simple answer is that declaring a function as pass-by-reference:

void foo(int& x);

is all we need. It's then passed by reference automatically.

You now call this function like so:

int y = 5;
foo(y);

and y will be passed by reference.

You could also do it like this (but why would you? The mantra is: Use references when possible, pointers when needed) :

#include <iostream>
using namespace std;

class CDummy {
public:
    int isitme (CDummy* param);
};


int CDummy::isitme (CDummy* param)
{
    if (param == this) return true;
    else return false;
}

int main () {
    CDummy a;
    CDummy* b = &a;             // assigning address of a to b
    if ( b->isitme(&a) )        // Called with &a (address of a) instead of a
        cout << "yes, &a is b";
    return 0;
}

Output:

yes, &a is b

Solution 2

A reference is really a pointer with enough sugar to make it taste nice... ;)

But it also uses a different syntax to pointers, which makes it a bit easier to use references than pointers. Because of this, we don't need & when calling the function that takes the pointer - the compiler deals with that for you. And you don't need * to get the content of a reference.

To call a reference an alias is a pretty accurate description - it is "another name for the same thing". So when a is passed as a reference, we're really passing a, not a copy of a - it is done (internally) by passing the address of a, but you don't need to worry about how that works [unless you are writing your own compiler, but then there are lots of other fun things you need to know when writing your own compiler, that you don't need to worry about when you are just programming].

Note that references work the same way for int or a class type.

Solution 3

Ok, well it seems that you are confusing pass-by-reference with pass-by-value. Also, C and C++ are different languages. C doesn't support pass-by-reference.

Here are two C++ examples of pass by value:

// ex.1
int add(int a, int b)
{
    return a + b;
}

// ex.2
void add(int a, int b, int *result)
{
    *result = a + b;
}

void main()
{
    int result = 0;

    // ex.1
    result = add(2,2); // result will be 4 after call

    // ex.2
    add(2,3,&result); // result will be 5 after call
}

When ex.1 is called, the constants 2 and 2 are passed into the function by making local copies of them on the stack. When the function returns, the stack is popped off and anything passed to the function on the stack is effectively gone.

The same thing happens in ex.2, except this time, a pointer to an int variable is also passed on the stack. The function uses this pointer (which is simply a memory address) to dereference and change the value at that memory address in order to "return" the result. Since the function needs a memory address as a parameter, then we must supply it with one, which we do by using the & "address-of" operator on the variable result.

Here are two C++ examples of pass-by-reference:

// ex.3
int add(int &a, int &b)
{
    return a+b;
}

// ex.4
void add(int &a, int &b, int &result)
{
    result = a + b;
}

void main()
{
    int result = 0;

    // ex.3
    result = add(2,2); // result = 2 after call
    // ex.4
    add(2,3,result); // result = 5 after call
}

Both of these functions have the same end result as the first two examples, but the difference is in how they are called, and how the compiler handles them.

First, lets clear up how pass-by-reference works. In pass-by-reference, generally the compiler implementation will use a "pointer" variable in the final executable in order to access the referenced variable, (or so seems to be the consensus) but this doesn't have to be true. Technically, the compiler can simply substitute the referenced variable's memory address directly, and I suspect this to be more true than generally believed. So, when using a reference, it could actually produce a more efficient executable, even if only slightly.

Next, obviously the way a function is called when using pass-by-reference is no different than pass-by-value, and the effect is that you have direct access to the original variables within the function. This has the result of encapsulation by hiding the implementation details from the caller. The downside is that you cannot change the passed in parameters without also changing the original variables outside of the function. In functions where you want the performance improvement from not having to copy large objects, but you don't want to modify the original object, then prefix the reference parameters with const.

Lastly, you cannot change a reference after it has been made, unlike a pointer variable, and they must be initialized upon creation.

Hope I covered everything, and that it was all understandable.

Solution 4

Passing by reference in the above case is just an alias for the actual object.

You'll be referring to the actual object just with a different name.

There are many advantages which references offer compared to pointer references.

Share:
220,024
KNU
Author by

KNU

Kunal's (definitely) not Unix @kunalkrishna85

Updated on July 09, 2022

Comments

  • KNU
    KNU almost 2 years

    The usual way to pass a variable by reference in C++(also C) is as follows:

    void _someFunction(dataType *name){ // dataType e.g int,char,float etc.
    /****
    definition
    */
    }
    
    int main(){
        dataType v;
        _somefunction(&v);  //address of variable v being passed
        return 0;
    }
    

    But to my surprise, I noticed when passing an object by reference the name of object itself serves the purpose(no & symbol required) and that during declaration/definition of function no * symbol is required before the argument. The following example should make it clear:

    // this
    #include <iostream>
    using namespace std;
    
    class CDummy {
      public:
        int isitme (CDummy& param);     //why not (CDummy* param);
    };
    
    int CDummy::isitme (CDummy& param)
    {
      if (&param == this) return true;
      else return false;
    }
    
    int main () {
      CDummy a;
      CDummy* b = &a;
      if ( b->isitme(a) )               //why not isitme(&a)
        cout << "yes, &a is b";
      return 0;
    }
    

    I have problem understanding why is this special treatment done with class . Even structures which are almost like a class are not used this way. Is object name treated as address as in case of arrays?

    • juanchopanza
      juanchopanza over 10 years
      Your premise is wrong: the correct way(s) to pass an object by reference in C++ is void someFunction(dataType& name) or void someFunction(const dataType& name). In C++, the word reference has a specific meaning.
    • user1837009
      user1837009 over 10 years
      I suggest you will need read some C++ book. You are muddle pass by pointer (first your variant) and pass by reference (second).
    • Benjamin Lindley
      Benjamin Lindley over 10 years
      "I have problem understanding why is this special treatment done with class . Even structures which are almost like a class are not used this way." -- It's not special treatment for classes. Structures are used this way. Even simple builtin types (int, char, double, etc...) are used this way. Where are you getting your information about C++?
    • KNU
      KNU over 10 years
      @BenjaminLindley Do you mean to say, we can pass simple builtin types (int, char, double, etc...) as somefunction(v) and think it is being passed by reference??? All I want to know is: If there is a Class _fruit and Mango being an object of this class. How can I pass address of Mango to a function - simply by using name Mango or &Mango.
    • Benjamin Lindley
      Benjamin Lindley over 10 years
      If you want to pass the address of an object, of any type (any class or struct, or buitlin type), you first need a function which accepts an address (or pointer). That function would have a signature like this: void somefunction(int * name) -- And you would pass it to the function like this: int v; somefunction(&v); -- If you want to pass an object (again, of any type) by reference (in the C++ sense), first you need a function with a signature like this: void somefunction(int & name) -- Then you can pass it like this: int v; somefunction(v);
    • Benjamin Lindley
      Benjamin Lindley over 10 years
      Note that I just used int in that demonstration in both cases, but it doesn't matter what the type is. You can use absolutely any class or struct or builtin type in either of those two ways. (actually, there are some exceptions, but you only have to worry about them if you work with evil programmers who overload the unary & operator for their classes, and you shouldn't work with those people, they are evil)
    • Benjamin Lindley
      Benjamin Lindley over 10 years
      Also, you seem to make a distinction between "variable" and "object". We don't do that in C++. There are some differences between builtin types and class types, mostly due to history. But for the most part the language tries hard, and mostly succeeds to make sure both are first class citizens in the language which are treated identically.
    • KNU
      KNU over 10 years
      @BenjaminLindley just got that point after reading Keyser's answer. Your's is even more descriptive. If you can copy above comment and post as answer.
    • KNU
      KNU over 10 years
      the output yes, &a is b made me paranoid since it was passing a and outputting about &a. But now I learnt that merely calling a doesn't determine weather it is called by value or by by reference. It is determined only after matching arguments in function definition.
  • keyser
    keyser over 10 years
    @BenjaminLindley Actually, I'm a student trying out everything. I'm currently doing nothing but c++ after 6 months of python :)
  • Benjamin Lindley
    Benjamin Lindley over 10 years
    There are references in C, it's just not an official language term like it is in C++. "reference" is a widely used programming term that long predates the C++ standardizing of it. Passing a pointer to an object is passing that object by reference.
  • Benjamin Lindley
    Benjamin Lindley over 10 years
    Ah, okay. I just looked at your profile and saw Java as the most frequently used language tag. I'll leave my upvote, for now. :)
  • KNU
    KNU over 10 years
    @Keyser yes, till now I thought only way to declare a function (using *) and call them(using &) (to exploit call by reference) was as shown in my 1st code above. but your answer was an eye opener to me. 100% satisfied.
  • keyser
    keyser over 10 years
    @KunalKrishna Glad I could help!
  • VansFannel
    VansFannel over 8 years
    I don't understad why you do this: CDummy* b = &a;
  • keyser
    keyser over 8 years
    @VansFannel that's from the original question
  • shivam
    shivam almost 4 years
    "A reference is really a pointer with enough sugar to make it taste nice". I'm going to print it, frame it and hang it on my wall :)
  • Sam Ginrich
    Sam Ginrich about 2 years
    According to Benjamin: If you have a pointer, e.g. int *a, then *a is precisely a reference.