在大学的最后几年,我有一门关于编译器的课程。我们为C的子集创建了一个编译器。我一直想知道如何在C ++中将pass-by-ref函数调用编译成汇编。
根据我的记忆,pass-by-val函数调用遵循以下过程:
传递参考有什么不同? (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;
}
我知道在byP(A *)中,v是按值传递的,因此,它不会影响调用者的参数。那么,你如何用A *?
来实现byRef(A&amp;)答案 0 :(得分:6)
您将指针传递给referand,就像您使用任何其他指针一样,并且被调用者知道如何使用它。因此,根据实现,它可能不在堆栈中 - 某些参数在某些调用约定中的寄存器中传递。
可能有其他方法可以做到这一点,因为C ++标准没有指定如何实现引用,即使它们是作为指针实现的,我想它们可能在调用约定中被区分。但是,指针是最明显的实现方式。
答案 1 :(得分:4)
通过引用调用将涉及将指针传递给值而不是值本身的副本。如果您对血腥细节感兴趣,可以让编译器发出汇编语言并自行检查。
编辑:您的指针示例应该是:
int byP (A* v) {
* v = A(4); // modify thing referenced by the pointer
return 0;
}
答案 2 :(得分:4)
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!";
}
};
然后“赋值”将在byRef
函数中输出,但不会在byP
函数中输出。
尽管&
是使用“引擎盖下的指针”实现的,正如其他人所说,它们被视为通过语言传递给函数的对象。
所以,使用指针实现byRef
:
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;
}
答案 3 :(得分:0)
不同之处在于它传递参数的地址,而不是参数的值。
答案 4 :(得分:0)
我没有看过类似GCC的实现,但一般的想法是,不是传递变量的内容,而是传递其地址(就像C ++代码使用“*”而不是参数上的“&amp;”。
其他方案可用,但通常可以通过推送堆栈上的值(或地址)来完成。
答案 5 :(得分:0)
我认为在pass-by-val中,程序将是: *存储PP的值 *将参数推入堆栈 *执行功能调用 *在函数中,从堆栈弹出参数
并且在pass-by-ref中,程序将是您编写的程序
欢呼声
答案 6 :(得分:0)
你可以自己看看。许多调试器允许您在代码和反汇编视图之间切换。我在代码视图中的函数调用上设置了一个断点,运行app到那一点,切换到程序集,然后跳过每个命令。
[SPOILER ALERT]
这是一个指针。
答案 7 :(得分:0)
当通过值传递时,编译器会发出代码以将源字节按位复制到目标变量。对于大型结构和/或频繁分配,这可能会非常低效。如果你的结构覆盖赋值运算符,它将被调用,然后你可以控制复制的内容,但是你仍然在堆栈上推送整个结构。
当通过引用传递时,struct的地址被压入堆栈,这只是一个int。这是传递大型对象的最有效方法。
当通过指针传递时,指针的地址被推送到堆栈上。必须取消引用指针才能获取结构的地址。还有一项额外的操作。
顺便说一下,byP函数中存在一个严重错误:它正在为指针分配一个临时局部变量。结构在堆栈上分配,并且很可能在它超出范围后被覆盖。根据Neil Butterworth的例子,您必须使用“new”在堆上分配它,或者将结构分配给指针引用的值。