C++ c++;by ref参数传递是否在汇编中编译?

C++ c++;by ref参数传递是否在汇编中编译?,c++,assembly,compiler-construction,C++,Assembly,Compiler Construction,在大学的最后几年,我上了一门关于编译器的课程。我们为C的一个子集创建了编译器。我一直想知道如何将C++中的Reby by函数调用编译成汇编。 我记得,pass by val函数调用遵循以下过程: 存储PP的地址 将参数推送到堆栈上 执行函数调用 在函数中,从堆栈中弹出参数 参考传递有什么不同?(int void(int&);) 编辑: 我可能听上去完全不知所措,但如果你能帮助我,我将非常感激 每个人的答案基本上是它传递的是地址而不是值。我知道传递指针基本上就是这样。那么,为什么这两个函数的行

在大学的最后几年,我上了一门关于编译器的课程。我们为C的一个子集创建了编译器。我一直想知道如何将C++中的Reby by函数调用编译成汇编。

我记得,pass by val函数调用遵循以下过程:

  • 存储PP的地址
  • 将参数推送到堆栈上
  • 执行函数调用
  • 在函数中,从堆栈中弹出参数
参考传递有什么不同?(int void(int&);)

编辑:

我可能听上去完全不知所措,但如果你能帮助我,我将非常感激

每个人的答案基本上是它传递的是地址而不是值。我知道传递指针基本上就是这样。那么,为什么这两个函数的行为会不同呢

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;
}
结构A{ int x; A(国际五){ x=v; } }; int byRef(A&v){ v=A(3); 返回0; } int byP(A*v){ v=&A(4);//或新的A(4) 返回0; } int _tmain(int argc,_TCHAR*argv[] { A A(1); A b(2);; byRef(a),byP(b),;
cout区别在于它传递的是参数的地址,而不是参数的值。

您传递一个指向refereand的指针,就像传递任何其他指针一样,被调用方知道如何使用它。因此,根据实现的不同,它可能不在堆栈上-某些参数在某些堆栈的寄存器中传递呼叫约定


可能还有其他方法,因为C++标准没有指定引用是如何实现的,即使它们被实现为指针,我猜想它们可能在调用约定中被区分。但是指针是最明显的实现。

< P>我没有查看GCC的实现,但是一般的想法是,在变量的内容中传递,而不是传递到它的地址(就像C++代码使用了“*”而不是“和”在参数上)。
其他方案也可用,但通常这将通过在堆栈上推送值(或地址)来实现。

引用调用将涉及传递一个指向值的指针,而不是值本身的副本。如果您对血腥的细节感兴趣,您可以让编译器发出汇编语言并自己检查它

编辑:您的指针示例应该是:

int byP (A* v) {
    * v = A(4);    // modify thing referenced by the pointer
    return 0;
}

我认为在pass by val中,程序是: *存储PP的值 *将参数推送到堆栈上 *执行函数调用 *在函数中,从堆栈中弹出参数

在passbyref中,这个过程就是你写的


干杯

你可以自己看看。许多调试器允许你在“代码”视图和“反汇编”视图之间切换。我会在“代码”视图中的函数调用上设置一个断点,运行应用程序到该点,切换到程序集,然后跳过每个命令

[剧透警报]

这是一个指针

int byRef(A& v){
  v = A(3);
  return 0;
}
这将调用临时对象对引用传递的对象的赋值,修改函数调用中使用的对象。如果未提供赋值运算符,将执行浅层复制

int byP   (A* v){
  v = &A(4); //OR new A(4)
  return 0;
}
这会将指向临时对象的指针复制到传入的指针值。未调用赋值函数。“v”的值已更改,但v指向的对象(作为参数传递的对象地址)不变

如果您这样做:

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

当通过值传递时,编译器会发出代码,将源字节按位复制到目标变量。对于大型结构和/或频繁赋值,这可能会变得非常低效。如果您的结构重写赋值运算符,则会调用它,然后您可以控制复制的内容,但您仍然无法执行将整个结构放在堆栈上

通过引用传递时,结构的地址被推送到堆栈上,这只是一个int。这是传递大型对象最有效的方法

当通过指针传递时,指针的地址会被推送到堆栈上。必须取消对指针的引用才能获得结构的地址。这涉及到一个额外的操作


顺便说一句,byP函数中有一个严重的错误:它给指针分配了一个临时局部变量。结构是在堆栈上分配的,并且在超出范围后(很可能)会被覆盖。您必须使用“new”根据Neil Butterworth的例子,将其分配给堆,或者将结构赋值给指针,根据/tp>将所有的参数推到堆栈上就是C abi。C++可以使用可选的ABI,其中参数在寄存器中传递。“*v=A(3);“谢谢你们,伙计们!最后真的很简单。我想我想把它复杂化:)
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;
}