Why do programmers say that "following a reference" really "passes references by value?" Why is it important?

I know the whole concept of passing by reference in C and C ++, and a similar concept is only passed by value in Java. But in the point of view, everything goes by value, doesn't it? In C, we pass a variable pointer to a function. Therefore, we just pass the value of the function reference. And it is for this reason that we say that Java does not support passing by reference, because we are simply passing the value of the reference variable in the function. Therefore, we pass the reference by value. Although there is a way to pass by reference in C ++ since we can pass arguments and the function will run at the same memory address using this format

void swap(int &x, int &y)

      

But passing by reference by pointers in C is just passing pointers by value.

void swap(int* x, int* y)

      

I know the question might sound a little silly, but I feel like I have a big hole in the whole concept. So what is the actual protection of call by reference, is it just the name of pseduo to call by value in a different context?

+3


source to share


4 answers


Two main points:

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

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

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



Why do programmers say that "pass by reference" really "passes references by value?"

By skipping references / pointers to original variables, in fact objects / addresses are passed by value. Thus, you can say that passing by reference is passing a reference by value, but that does not mean that pass by reference is a pass by value pseudo-name. The difference between the two is well explained in this answer . I am copying an excerpt:

If I give you the url, I pass by link. ... You can use this url to see the same webpage that I see. If this page is changed, we both see the changes. If you delete the URL, everything you do destroys your link to that page - you don't delete the page itself.

If I print a page and give you a printout, I pass the value . Your page is a disabled copy of the original. You will not see any subsequent changes, and any changes you make (such as sketches on a printout) will not appear on the original page. If you destroy the printout, you have effectively destroyed your copy of the object, but the original web page remains intact.

+3


source


Passing by reference means that the parameter of the called functions will be the same as the passed argument of the callers (not the value, but the identifier is the variable itself). Passing by value means that the parameter of the called functions will be a copy of the passed argument of the callers. The value will be the same, but the identifier - the variable - is different. Thus, changes in a parameter executed by the called function in one case change the passed argument, and in the other case, just change the parameter value in the called function (which is just a copy).

Simple example in C ++



#include <iostream>

void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }

int main()
{
    int x = 0;
    by_val(x); std::cout << x << std::endl;  // prints 0
    by_ref(x); std::cout << x << std::endl;  // prints 2

    int y = 0;
    by_ref(y); std::cout << y << std::endl;  // prints 2
    by_val(y); std::cout << y << std::endl;  // prints 2
}

      

+4


source


C ++ is defined by standard modular errors. The C ++ standard does not specify how references are executed and how they are passed to functions. It also doesn't define calling conventions at all, nor does it define pointer layout, stack, heap, or many other implementation details.

Instead, it tries to define what the C ++ code means.

Links are ultimately aliases for other meanings. The most common way to implement them is like a pointer under the hood: but since it is impossible to access that pointer value, as well as the side effects of accessing through it, this makes it easier for compilers to completely eliminate the existence of a reference, and just use the specified value directly.

If a compliment cannot do this, it usually conveys a pointer or equivalent.

Despite the fact that it is often used as a pointer, it still differs in that the semantics of interacting with it are different: they cannot be reset, they cannot have their own address, and they cannot be uninitialized (null or equivalent).

Naturally, these rules can be violated with undefined behavior.

+3


source


You cannot say that pass by reference really does pass references by value without defining a reference.

In Java, the statement is true (to a first approximation) because inside a function, you can change the value of a formal parameter that is a reference without changing the value of the parameter passed to call:

void f(Object param) {
  param = null;
}

void g() {
  Object o = new Object();
  System.out.println(o);
  f(o);
  System.out.printn(o);
}

      

Everyone knows that two print operators will give accurate results. In fact, there is no reference traversal in Java, there are only references that can be passed; and there is only one way to pass arguments: by value.

In C ++, this is really different. When the value of the link parameter changes inside the function, the parameter is passed on change:

void f(int &param) {
  param = 0;
}

void g() {
  int i=12;
  cout << i << endl;
  f(i);
  cout << i << endl;
}

      

Every C ++ programmer knows that the second print will display 0 (while the first one is 12).

So in C ++ you cannot say that "pass by reference" means "pass by reference". In C ++, references do not matter, they are just names associated with chunks of memory (Standard Section 8.3.2 Reference: [Note: A reference can be thought of as an object name. - end note). There f()

is only one variable inside , which has two names. Of course, you might argue that most C ++ implementations of references are hidden pointers, so the statement might be true; but you should be aware that there are many cases where it is possible to avoid using hidden pointers to implement references (standard 8.3.2 / 7 Reference sections. Not specified if this reference is required to store) ... So in C ++ the assertion is invalid ... C ++ has two ways of passing parameters: by value and by reference.

+1


source







All Articles