Does C++ Pass Objects by Value or Reference

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]).

C++: Reasons for passing objects by value

ALWAYS use pointers when using objects as arguments

No, in C++ always pass by reference, unless your function can be called with nullptr as a valid argument. If the function does not need to modify the argument, pass by const reference.

Passing arguments by value has several uses.

If your function needs to create a copy of the argument it is better to create this copy by passing by value rather than creating a copy within the function. For instance:

void foo( widget const& w )
{
widget temp( w );
// do something with temp
}

Instead use

void foo( widget w )  // copy is made here
{
// operate on w itself
}

Doing this also has the benefit of allowing the compiler to move widget if possible, which is generally more efficient than creating copies.

Is Objective-C pass-by-value or pass-by-reference?

C does not support pass-by-reference and Objective-C, being a strict superset of C doesn't either.

In C (and Objective-C) you can simulate pass-by-reference by passing a pointer, but it's important to remember that you're still technically passing a value, which happens to be a the value of a pointer.

So, in Objective-C (and C, for the matter) there is no concept of reference as intended in other languages (such as C++ or Java).

This can be confusing, so let me try to be clearer (I'll use plain C, but - again - it doesn't change in Objective-C)

void increment(int *x) {
*x++;
}

int i = 42;
increment(&i); // <--- this is NOT pass-by-reference.
// we're passing the value of a pointer to i

On the other hand in C++ we could do

void increment(int &x) {
x++;
}

int i = 41;
increment(i); // <--- this IS pass-by-reference
// doesn't compile in C (nor in Objective-C)

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.

Does C even have pass by reference ?

C parameters are always passed by value rather than by reference. However, if you think of the address of an object as being a reference to that object then you can pass that reference by value. For example:

void foo(int *x)
{
*x = 666;
}

You ask in a comment:

So why do we need pointers in C when we can pass all the parameters by value?

Because in a language that only supports pass-by-value, lack of pointers would be limiting. It would mean that you could not write a function like this:

void swap(int *a, int *b)
{
int temp = *a;
*b = *a;
*a = temp;
}

In Java for example, it is not possible to write that function because it only has pass-by-value and has no pointers.

In C++ you would write the function using references like this:

void swap(int &a, int &b)
{
int temp = a;
b = a;
a = temp;
}

And similarly in C#:

void swap(ref int a, ref int b)
{
int temp = a;
b = a;
a = temp;
}

Why do programmers say that pass by reference is really passing references by value? Why is that important?

Two main points:

  • There is no call by reference in C.
  • Pass by value and pass by reference are different. They are not same.

Pass by value: the called function creates a new set of variables in stack and copies the values of the arguments into them.

Pass by reference: instead of passing values to the function being called, references/pointers to the original variables are passed.

Why do programmers say that “pass by reference” is really “passing references by value?”

In passing references/pointers to the original variables, in fact objects/addresses are passed by value. So, you can say pass by reference is passing reference by value but this doesn't imply that pass by reference is pseudo name of pass by value. The difference between the two is well explained in this answer. I am copying the excerpt:

If I tell you the URL, I'm passing by reference. You can use that URL to see the same web page I can see. If that page is changed, we both see the changes. If you delete the URL, all you're doing is destroying your reference to that page - you're not deleting the actual page itself.

If I print out the page and give you the printout, I'm passing by value. Your page is a disconnected copy of the original. You won't see any subsequent changes, and any changes that you make (e.g. scribbling on your printout) will not show up on the original page. If you destroy the printout, you have actually destroyed your copy of the object - but the original web page remains intact.

Where should I prefer pass-by-reference or pass-by-value?

There are four main cases where you should use pass-by-reference over pass-by-value:

  1. If you are calling a function that needs to modify its arguments, use pass-by-reference or pass-by-pointer. Otherwise, you’ll get a copy of the argument.
  2. If you're calling a function that needs to take a large object as a parameter, pass it by const reference to avoid making an unnecessary copy of that object and taking a large efficiency hit.
  3. If you're writing a copy or move constructor which by definition must take a reference, use pass by reference.
  4. If you're writing a function that wants to operate on a polymorphic class, use pass by reference or pass by pointer to avoid slicing.

can somebody explain me what does passing by value and Passing by reference mean in C#?

In simple terms...

"Passing by value" means that you pass the actual value of the variable into the function. So, in your example, it would pass the value 9.

"Passing by reference" means that you pass the variable itself into the function (not just the value). So, in your example, it would pass an integer object with the value of 9.

This has various consequences, and each is useful in different situations.

This answer has more thorough information:
What's the difference between passing by reference vs. passing by value?



Related Topics



Leave a reply



Submit