3

If I pass a variable to a function but mark that variable as constant will it automatically get passed by reference?


In C++

void foo(const int a)

After testing: No because it prints different memory locations.

void foo(const int a)
{
    cout << &a << endl;
}

int main()
{
   int a = 5;
   foo(a);
   cout << &a << endl;
   return 0;
}

C

No right? Because I can only pass a pointer to the memory location, not really by reference. Like here: Passing by reference in C


Java

Maybe the compiler can figure out that final should point to the same memory location?

void foo(final int a)

C#

Same as Java?

void foo(const int a)


I know I included 4 languages in my question but since I use those 4 languages a lot I want to know.

Is there a way to force Java and C# to handle do this? I know in C++ I can add & to the function and it will be exactly what I want.

 void f(const int &a)

Pretty much that is what I am hopping Java and C# compilers are doing behind the scenes.

Community
  • 1
  • 1
J_Strauton
  • 2,270
  • 3
  • 28
  • 70
  • 3
    All of these are semantically pass-by-value. Could the compiler optimise under-the-hood? Sure, it's possible. – Oliver Charlesworth Aug 29 '14 at 22:16
  • I'm going to guess that you asked this because you frequently see C++ function protypes take a reference to a const object as a parameter. That is an intentional optimization, to allow functions parameter values to be rvalues without having to copy them for the function call (and C++11 adds rvalue references, as an alternative). But, a const function parameter is not going to be passed by reference by default. – Sam Varshavchik Aug 29 '14 at 22:23
  • 1
    +1 for a question with multiple language tags that's actually relevant to them all. – jdphenix Aug 29 '14 at 22:43
  • 1
    Java primitives have no reference. Java is always pass by value. – Elliott Frisch Aug 29 '14 at 22:45
  • @jdphenix: It's relevant to all in the sense that the OP is asking the same question about 4 languages in parallel. – Oliver Charlesworth Aug 29 '14 at 22:54
  • 2
    What is the purpose of your question "Is there a way to force Java and C# to handle [] this"? If you want to pass the same memory location so that the method can modify the parameter and allow the caller to see the modified value, there are ways to get this to happen in Java (I don't know C# well enough). But if not, then why are you hoping the compiler passes the address behind the scenes, and why do you care? Note that passing an `int` by address tends to make programs slower since it requires indirection to access the value. – ajb Aug 29 '14 at 22:54
  • @ajb because I want the variable to be constant, then I don't want it to be modified. I want it to be passed by reference and constant so that the variable is not copied and so the program saves RAM. – J_Strauton Aug 29 '14 at 23:28
  • @J_Strauton: It probably doesn't even use RAM. Profile before trying to make micro-optimizations. – Oliver Charlesworth Aug 29 '14 at 23:30
  • @J_Strauton Parameters of primitive types are most likely passed in registers, not by copying RAM. And if you passed it by reference, the program would have to copy the address somewhere, and the address will be at least as big as a 32-bit `int` and possibly bigger, on most processors. – ajb Aug 29 '14 at 23:51
  • @OliCharlesworth I thought when a function was called stack space was allocated for the variables, the return value, and the **parameters**. – J_Strauton Aug 30 '14 at 14:39

3 Answers3

4

In Java, all the variables are passed by value.

Primitives are actually copied and object variables are references anyway, meaning that the value of an object variable is actually the reference -> you are passing the reference's value.

Nevertheless, you always pass by value, same as in C++, you will pass by value if you don't use the reference explicitly.

I'm almost certain that it's the same in C#.

Edit: I forgot about C

It's the same in C: pass by value by default. Obviously, you can pass a pointer. In C++, this is extended so you can take a reference as a parameter:

void function(int& intByReference) {
    cout<<&intByReference<<endl; //prints x
}

int main() {
    int n = 0;
    cout<<&n<<endl; //prints x
    function(n);
}

As C++ includes classes, there is a default constructor to copy the object:

class MyClass {

    public:
        MyClass(MyClass& objectToCopy) {
            //copy your object here
            //this will be called when you pass an instance of MyClass to a function
        }
};
J4v4
  • 780
  • 4
  • 9
  • What about the remaining parts? – J4v4 Aug 29 '14 at 22:38
  • C++ part too :-) you are actually passing by value, Objects are even copied with a constructor if you pass them directly. Having that in mind, It would only make sense that it's the same in C# - passing by value should be default, especially for primitives, it's the only thing that makes sense. – J4v4 Aug 29 '14 at 22:42
  • It's the same in C#. It's always pass by value unless the parameter is marked `ref` or `out`, in which case it is pass by reference. – newacct Aug 30 '14 at 07:53
1

You are making a mistake in thinking your intuition can guide you to how the details of the languages are implemented. This is quite simply not true. In the case of C++ and C, the spec states quite clearly how this should be dealt with.

Java as a pass by value language might have some provision for this behaviour in the specs for final/const/not touched values. (I don't know) But it is only the specs that can allow for this behaviour.

Captain Giraffe
  • 14,407
  • 6
  • 39
  • 67
  • 1
    This isn't entirely clear. You start by hinting that these are implementation details, but then go on to mention the spec, which has nothing to do with implementation details... – Oliver Charlesworth Aug 29 '14 at 23:22
  • @OliCharlesworth No I'm saying he is extrapolating intuition onto what is covered by the spec. Please edit or suggest an edit if I'm unclear on that. – Captain Giraffe Aug 29 '14 at 23:25
0

Before answer your question let me illustrate an example to test your scenario.

Suppose you call a method void called(int a ) from method void calledFrom() by passing a variable int a.

In my understanding :

If change of value of a in any method effect another (change of a in calledFrom effect the value of a in called) then its called by reference otherwise its called by value.

Now lets test this in java using final

public class MyClass
{
    int a;
    public void setA(final int a)
    {
        this.a=a;
    }
    public void printA()
    {
        System.out.println(a);
    }

}

from main method you do this:

int a=10;
MyClass mclass=new MyClass();

mclass.setA(a);
mclass.printA();
a++;
mclass.printA();

the output is : 10 10

so changing in main not changing the value of a in MyClass. so call to public void setA(final int a) was not a called by reference it was call by value.

The key final may be arising some confusion. When you writing final in method signature is not going to effect is behavior in any other way except you cant change the value of that parameter inside that method. as for example if you write

public void setA(final int a)
{
    a++; //error
    this.a=a;
}

you will get a compilation error

but you can esealy do this

 public void printA()
{
    a++; //ok
    System.out.println(a);
}

I think this is not only in java all other languages have the same behavior . you can try in other languages .

to get a clear concept about pass by value and pass by reference in context of java you can read this thread

or read this answer

Community
  • 1
  • 1
Saif
  • 6,804
  • 8
  • 40
  • 61