c++的do引用占用内存

C++ do references occupy memory

本文关键字:内存 引用 do c++      更新时间:2023-10-16

我已经读到,引用只是一个别名存在于符号表中的变量。考虑下面的代码

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吗?

谁能详细解释一下吗?

你的函数有四个参数

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

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

在这个上下文中,引用实际上只是一个伪装的指针。当你在局部作用域中有一个引用引用一个局部作用域中的对象时,大多数c++编译器实际上会把它优化掉,这样引用就不会占用任何实际的内存。

但是函数调用是一个全新的游戏。函数期望接收到某个对象的引用。函数不能通过心灵感应知道传递给它的引用是什么。调用函数的对象负责提供引用形参。不用说,需要几个字节来传递该信息,即作为引用传递的对象的地址(我最近提到过指针吗?)

如果函数是用static作用域声明的(没有外部链接),并且选择了一个足够积极的优化级别进行编译,那么c++编译器将内联函数调用,并且能够优化引用参数。

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

用更一般的方式回答你的问题:c++标准不要求引用必须占用内存,但也不要求它们不应该占用内存。c++编译器可以自由地以任何方式编译代码,只要结果是正确的,并且符合预期。如果在特定情况下,c++编译器找出了如何优化一个引用,使其实际上不作为独立的对象"存在",那么它可以自由地这样做。但这不是必需的

引用比"符号表中其他东西的别名"要复杂得多。事实上,这个定义通常并不适用。例如,引用形参不能只是别名为"符号表中的其他内容",因为那样会防止调用带有多个不同实参值的函数。

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

请注意,除非您需要通过自动存储("在堆栈上")获取对象的地址,否则编译器不需要实际将其放入堆栈中。它可以完全存在于寄存器中,也可以完全被优化掉。例如,使用这个函数:

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

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

我认为这与基指针改变有关

如果编译器只是想将它们作为别名实现,那么无论何时函数使用引用,我们都需要将其替换为原始地址,但由于该引用来自堆栈中的函数,因此该地址将具有(Basepointer - offset)的形式。但是在进入这个新函数(即test)时,我们在开始时改变了BP,所以它不再可能了,所以我们需要实现这个引用一个指针,这占用了内存。