C++中的按引用传递

3
调用函数时传递给函数的是指针的副本,而不是原始数据。这意味着函数可以使用指针来访问和更改原始数据,从而影响调用函数的代码中的变量。
void foo(int &a,int &b)

当我写下

foo(p,q)

函数实际传递的是什么?它是p和q的地址吗?


我假设你知道引用和指针之间的编程差异,对吧?你是在问它被编译成什么样子吗? - J Teller
@Peter 那么,为什么不直接查看生成的代码呢? - anon
我该如何做到这一点?我正在使用gcc编译器。 - Bruce
gcc -S 命令会给你一个汇编代码来查看。 - Martin Tilsted
@Peter 最简单的检查代码的方法是在调试器中运行它,例如 gdb,或者如果你想要一个图形界面,可以使用 Insight 或 DDD。 - anon
5个回答

6
实际传递给函数的是引用。命名参数b成为参数对象q的同义词。
编译器可能实现的方式是,在调用之前,调用者将q的地址放在堆栈或寄存器中,调用方使用该值来影响所有对b的访问。但是,将其描述为“实际传递”指针可能会引起误解,因为参数传递是C++语言层面上的概念,在那个层面上,它与传递指针并不是相同的概念。例如,当你传递一个指针时,你可以传递一个空指针,但是当你传递一个引用时,你不能(有效地)传递空值。因此,说它们是同一件事情是错误的。
尽管如此,实现编译器的人可能会将其描述为“实际传递指针”,你知道他们的意思。举个例子,如果在调用约定中,char变量占据4字节的堆栈插槽,则他们可能会说编译器“实际上传递了int”。所以这取决于“实际上”的含义。

1
"这取决于“实际上”应该是什么意思" ... 政治家? - Seth

3
其他答案提到了引用和指针之间的语义差异。
实际上,我曾经使用过的每个编译器都以相同的方式实现它们——传递引用实际上是在汇编级别传递指针。这并没有在任何标准中指定,但在实践中普遍存在。
这个问题之前在SO上出现过:指针和引用之间的低级差异是什么?

2

实际上,它传递的是引用类型——有点像地址,但又不完全一样。实际地址应该是一个指针。引用比指针更弱,但可以说更安全。维基百科对指针和引用之间的区别有很好的描述。


1

你正在传递一个引用,它不是指针,也不是地址,但它很相似。

“引用”到底是什么并没有明确的定义。标准并没有规定处理引用的机制,只规定了使用引用的后果。通常情况下,它们会被实现为指针。

例如:

int foo(int& a, int& b) { a = b; }

// Usage
int x, y;
foo(x, y);

这可能会生成与以下代码相同的机器码:

int foo(int* a, int* b) { *a = *b; }

// Usage
int x, y;
foo(&x, &y);

但是这并不保证,两者并不等价(尽管它们提供类似的功能)。

当您获取引用的地址时,您将获得与其所引用的对象相同的地址。例如:

void foo(int& x) { std::cout << &x << std::endl; }

int y;
std::cout << &y << std::endl;
foo(); // This will print the same as above.

0

传递引用的方式由编译器定义。无论如何,它们都被传递为int&,这是C++中的实际类型。请尝试以下代码:

int x = 10;
int& y = x;
x = 100;

你认为 y 的值是多少?引用不完全是指针,而是变量的别名。编译器应用于 int& 的相同机制也用于按引用传递的参数。

给定以下程序:

void byRef(int& x)
{
    return;
}

void byVal(int x)
{
    return;
}

void byPtr(int * x)
{
    return;
}

int _tmain(int argc, _TCHAR* argv[])
{

    int x = 0;
    byRef(x);
    byVal(x);
    byPtr(&x);

    return 0;
}

byRefbyPtr调用生成的MSVC90汇编代码完全相同,如下所示:

lea eax, [x]
push eax
call byRef ;or byPtr
add esp, 4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接