C ++引用占用内存

时间:2016-09-14 02:37:39

标签: c++ reference pass-by-reference

我已经读过,引用只是符号表中存在的变量的别名。请考虑以下代码

int main()
{
    int y = 6;
    int &z = y;
    int k = 43;
    test(2,y,5,78);
    cout << &y << "\n";
    cout << &z << "\n";
    cout << &k << "\n";
}

void test(int a,int & x, int g, int h)
{
    cout << &a << "\n";
    cout << &x << "\n";
    cout << &g << "\n";
    cout << &h << "\n";
}

对于我得到的输出

0039F740
0039F848
0039F748
0039F74C
0039F848
0039F848
0039F830

如果引用不占用堆栈中的内存,为什么内存会被偏移。例如。在功能测试中,局部变量a为0039F740,但g为0039F748。不应该是0039F744吗?

有人可以深入解释一下吗?

2 个答案:

答案 0 :(得分:2)

您的功能有四个参数。

必须将每个参数传递给函数。

其中一个参数是参考的事实不会改变这个基本事实。您看到的额外空间是函数的参考参数。

在这种情况下,引用实际上只是伪装的指针。当你在引用本地作用域中的对象的本地作用域中有一个引用时,大多数C ++编译器确实会对它进行优化,以便引用不会占用任何实际的内存。

但是函数调用是一个全新的球类游戏。该函数期望接收对某个对象的引用。该功能无法通过心灵感知知道作为参考传递给它的是什么。无论调用什么函数,都负责提供参考参数。不言而喻,需要几个字节来传递这些信息,即作为参考传递的对象的地址(我最近提到了关于指针的东西吗?)

如果函数是使用static范围声明(没有外部链接),并且选择了足够激进的优化级别进行编译,那么你的C ++编译器将内联函数调用,并且能够优化参考参数。

但是声明具有外部链接的函数通常会导致编译器无法尝试内联函数调用。它将继续并生成一个完整的独立函数,期望拥有它有权使用的每个参数。

以更一般的方式回答您的问题:C ++标准并不要求引用占用内存,但并不要求它们不应占用内存。 C ++编译器可以以任何方式自由编译代码,只要结果是正确的,以及它们应该是什么。如果在特定情况下,C ++编译器会弄清楚如何优化引用,以使它实际上不存在&#34;存在&#34;作为自己的独立对象,可以自由地这样做。但并不要求这样做。

答案 1 :(得分:1)

引用比“符号表中别名的别名”更复杂。事实上,这个定义通常甚至不适用。例如,引用参数不能只是别名为“符号表中的其他内容”,因为这会阻止使用多个不同的参数值调用函数。

标准没有说明你应该怎么做,但引用的典型实现只是使用指针。如果您有int& x,则x会返回*(pointer)&x会返回(pointer)。指针确实占用内存,但是没有明确定义的C ++操作会发现支持引用的指针的存储位置。

请注意,除非您需要使用自动存储(“在堆栈上”)获取对象的地址,否则编译器不需要实际将其放在堆栈中。它可以完全存在于寄存器中,也可以完全优化掉。例如,使用此功能:

int foo(int a, int b) { return a + b; }

在具有System V调用约定的x86_64上,a在rdi寄存器中传递,brsi寄存器中传递,结果在rax中计算,并且该函数不需要触摸堆栈中的任何值。