问题就在标题里。 如果我在C++11中有以下代码:
int a, b = 20;
int &ra = a;
ra = b;
std::cout << ra << std::endl; //Prints 20
编译器是如何处理“RA”的,它是创建另一个var作为指针还是它只是一个别名,当编译器发现“RA”和说“a”是一样的?
是的。 而且,没有。 呵呵。 继续读下去。
这里有两层抽象在起作用,你应该试着理解这两层。
当您编写C++时,您正在描述一个程序。 你并不是在写指令让计算机执行。 那是编译器的工作。
在您的C++代码中,ra
只是一个别名。 它不是“物体”。 操作引用的语法很少,这是经过深思熟虑的:我们应该将ra
视为a
; 这是同一个东西的两个名字。
即使当我们深入钻研语言时,我们也能观察到这一点。 给定以下函数:
int bar = 42;
int& foo()
{
return bar;
}
…表达式foo()
不是引用! 这让很多人大跌眼镜。 这是一个“int
类型的lvalue”。 只是int
,而不是int&
。 它是一个表达式,用来“命名”您最初使用名称bar
声明的整数。 从概念上讲,它不是一个单独的,有诗意的东西,语言规则,类型和值类别证明了这一点。
当然,foo()
返回引用这一事实并不只是被忽略:这就是为什么不进行复制,以及为什么结果表达式的值类别为lvalue而不是rvalue。
因此,引用类型并不支持语言使用不同表达式在多个位置引用对象的能力:它们只给C++程序员提供了访问该能力的权限。
(不过,这里有时可能会出现“抽象泄漏”;例如,使用引用类型声明的类成员几乎必须占用存储空间,并且在我所知道的每个ABI中都将作为指针实现。这只是一种实际需要。)
我指的是编译器创建的实际计算机程序。 它包含目标计算机将执行的实际指令。
在这个真实的程序中,对于任何访问,可能有也可能没有一个指针的取消引用,甚至可能有也可能没有一个对象存储在内存中的某个地方。 相反,该值可能只是被烘焙到您的代码中。 有些人称之为“优化”,但实际上,它只是你的编译器产生了最好的计算机程序,具有你所描述的语义。
这不仅适用于引用,也适用于非引用。 例如,在任何适当的“优化”级别,您的整个实际程序可能只是将整数20
发送到std::cout
机器的代码; 在执行过程中,这些int
没有理由作为对象实际“存在”于任何内存位置。
因此,如果您真的关心性能,您需要阅读汇编代码来了解实际发生的情况。 否则,你不可能也不需要预测。
…没有真正的理由担心你的引用本身是别名还是“变量”,因为编译过程已经完全模糊了两者之间的区别。