Search code examples
c++assemblycompiler-construction

How does c++ by-ref argument passing is compiled in assembly?


In the late years of college, I had a course on Compilers. We created a compiler for a subset of C. I have always wondered how a pass-by-ref function call is compiled into assembly in C++.

For what I remember, a pass-by-val function call follows the following procedure:

  • Store the address of the PP
  • Push the arguments onto the stack
  • Perform the function call
  • In the function, pop from stack the parameters

What's different for pass-by-reference? (int void(int&);)

EDIT:

I may sound totally lost but, if you could help me I'd really appreciate it.

Everyone's answer is basically that it passes the address instead of the value. I understood that to be basically what passing a pointer is. So how come, these two functions, behave differently?:

struct A {
    int x;
    A(int v){
        x = v;
    }
};

int byRef(A& v){
    v = A(3);
    return 0;
}

int byP   (A* v){
    v = &A(4); //OR new A(4)
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    A a (1); A b (2);
    byRef(a); byP  (&b);
    cout << a.x << " " << b.x;

    system("pause");

    return 0;
}

I know that in byP(A*), v is being passed by value, thus, it won't affect the caller's argument. Then, how would you implement byRef(A&) in terms of A*?


Solution

  • int byRef(A& v){
      v = A(3);
      return 0;
    }
    

    This invokes the assignment of the temporary object to the object passed by reference, the object used in the function call is modified. A shallow copy will be performed if no assignment operator is provided.

    int byP   (A* v){
      v = &A(4); //OR new A(4)
      return 0;
    }
    

    This copies a pointer to a temporary object to the passed in pointer value. No assignment function is called. The value of 'v' is changed but the object v pointed to, the object address passed as an argument, is unchanged.

    If you did this:

    struct A {
      int x;
      A(int v){
        x = v;
      }
      A &operator = (A &rhs){
        cout << "assignment!";
      }
    };
    

    then the "assignment" will be output in the byRef function but not the byP function.

    Although the & is implemented using pointers 'under the hood', as others have said, they are treated as the object passed to the function by the language.

    So, to implement the byRef using pointers:

    int byRefUsingP (A *v)
    {
      *v = A(3);
      // or you could do:
      // v->operator = (A(3));
      // if an operator = is defined (don't know if it will work without one defined)
      return 0;
    }