Passing Object by Reference in C++

passing object by reference in C++

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

Passing by reference in C

Because you're passing the value of the pointer to the method and then dereferencing it to get the integer that is pointed to.

Passing a object by reference in c++

C++ has support for reference semantics. Therefore, for a given function:

void foo(Bar& bar);

To pass by reference you do:

int main() {
Bar whatsit;

foo(whatsit);

return 0;
}

That's it!

This is commonly confused with passing a pointer, where for a function such as:

void foo(Bar* bar);

You would do:

int main() {
Bar whatisit;

foo(&whatsit);

return 0;
}

The difference is mostly a matter of semantics:
- A reference is always valid. There is no reason to check for a NULL pointer.
- A pointer could be NULL, and as such, should be checked.

It is, however, possible for a reference to refer to a NULL pointer, however, if the programmer decides to be evil and abuse reference semantics, but the principle remains.

Does C++ pass objects by value or reference?

Arguments are passed by value, unless the function signature specifies otherwise:

  • in void foo(type arg), arg is passed by value regardless of whether type is a simple type, a pointer type or a class type,
  • in void foo(type& arg), arg is passed by reference.

In case of arrays, the value that is passed is a pointer to the first element of the array. If you know the size of the array at compile time, you can pass an array by reference as well: void foo(type (&arg)[10]).

Passing an object by reference (C++)

void Node::make_tree(Node* node, int values[], int size);

Node pointer cannot be modified inside the function, as you pass it by value (only the copy is modified).

You can use a reference, as suggested in comments :

 void Node::make_tree(Node* &node, int values[], int size);

Or you can also use a pointer to a pointer void Node::make_tree(Node** node, int values[], int size); but there will be more work to modify your code.

Passing objects by reference vs value

What I don't understand is what happens when I invoke a method, what actually happens. Does new() get invoked? Does it just automagically copy the data? Or does it actually just point to the original object? And how does using ref and out affect this?

The short answer:

The empty constructor will not be called automatically, and it actually just points to the original object.

using ref and out does not affect this.

The long answer:

I think it would be easier to understand how C# handles passing arguments to a function.

Actually everything is being passed by value
Really?! Everything by value?
Yes! Everything!

Of course there must be some kind of a difference between passing classes and simple typed objects, such as an Integer, otherwise, it would be a huge step back performance wise.

Well the thing is, that behind the scenes when you pass a class instance of an object to a function, what is really being passed to the function is the pointer to the class. the pointer, of course, can be passed by value without causing performance issues.

Actually, everything is being passed by value; it's just that when
you're "passing an object", you're actually passing a reference to that
object (and you're passing that reference by value).

once we are in the function, given the argument pointer, we can relate to the object passed by reference.

You don't actually need to do anything for this, you can relate directly to the instance passed as the argument (as said before, this whole process is being done behind the scenes).

After understanding this, you probably understand that the empty constructor will not be called automatically, and it actually just points to the original object.


EDITED:

As to the out and ref, they allow functions to change the value of an arguments and have that change persist outside of the scope of the function.

In a nutshell, using the ref keyword for value types will act as follows:

int i = 42;
foo(ref i);

will translate in c++ to:

int i = 42;    
int* ptrI = &i;
foo(ptrI)

while omitting the ref will simply translate to:

int i = 42;
foo(i)

using those keywords for reference type objects, will allow you to reallocate memory to the passed argument, and make the reallocation persist outside of the scope of the function (for more details please refer to the MSDN page)

Side note:

The difference between ref and out is that out makes sure that the called function must assign a value to the out argument, while ref does not have this restriction, and then you should handle it by assigning some default value yourself, thus, ref Implies the the initial value of the argument is important to the function and might affect it's behaviour.

Passing Objects By Reference or Value in C#

Objects aren't passed at all. By default, the argument is evaluated and its value is passed, by value, as the initial value of the parameter of the method you're calling. Now the important point is that the value is a reference for reference types - a way of getting to an object (or null). Changes to that object will be visible from the caller. However, changing the value of the parameter to refer to a different object will not be visible when you're using pass by value, which is the default for all types.

If you want to use pass-by-reference, you must use out or ref, whether the parameter type is a value type or a reference type. In that case, effectively the variable itself is passed by reference, so the parameter uses the same storage location as the argument - and changes to the parameter itself are seen by the caller.

So:

public void Foo(Image image)
{
// This change won't be seen by the caller: it's changing the value
// of the parameter.
image = Image.FromStream(...);
}

public void Foo(ref Image image)
{
// This change *will* be seen by the caller: it's changing the value
// of the parameter, but we're using pass by reference
image = Image.FromStream(...);
}

public void Foo(Image image)
{
// This change *will* be seen by the caller: it's changing the data
// within the object that the parameter value refers to.
image.RotateFlip(...);
}

I have an article which goes into a lot more detail in this. Basically, "pass by reference" doesn't mean what you think it means.

Passing object by reference to std::thread in C++11

Explicitly initialize the thread with a reference_wrapper by using std::ref:

auto thread1 = std::thread(SimpleThread, std::ref(a));

(or std::cref instead of std::ref, as appropriate). Per notes from cppreference on std:thread:

The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref).



Related Topics



Leave a reply



Submit