C++11 将变量作为左值引用。他们真的是“vars”还是只是“别名”?

Luc*_*as 0 c++ variables reference lvalue

嗯,问题在标题中。如果我在 C++11 中有以下代码:

int a, b = 20;
int &ra = a;
ra = b;
std::cout << ra << std::endl;     //Prints 20
Run Code Online (Sandbox Code Playgroud)

编译器如何处理“ra”,它是创建另一个var作为指针还是只是一个别名,当编译器发现“ra”时与说“a”相同?

Ast*_*ngs 8

是的。和不。呵呵。继续阅读。

这里有两个抽象层在起作用,您应该尝试理解它们。

语言

当您编写 C++ 时,您是在描述一个程序。您实际上并不是在为计算机编写要执行的指令。那是编译器的工作。

在您的 C++ 代码中,ra只是一个别名。它不是一个“对象”。操作引用的语法很少,这是故意的:我们应该将其ra视为存在 a;它们是同一事物的两个名称。

即使我们深入研究语言,我们也可以观察到这一点。给定以下函数:

int bar = 42;

int& foo()
{
   return bar;
}
Run Code Online (Sandbox Code Playgroud)

...该表达式foo() 不是参考!这让很多人感到惊讶。这是一个“左值类型int”。只是int,不是int&。这是一个表达式,它“命名”您最初使用 name 声明的整数bar。从概念上讲,它不是一个单独的、指针式的东西,语言规则和类型以及值类别证明了这一点。

当然,foo()返回引用的事实并没有被忽略:这就是为什么没有复制,以及为什么结果表达式具有值类别lvalue而不是rvalue

因此,引用类型并没有增强语言使用不同表达式在多个位置引用对象的能力:它们只是让您,C++ 程序员,可以访问这种能力。引用实际上只与声明有关。一旦程序通过了您的引用声明,您就不再真正处理引用了,因为实际上没有任何“引用”之类的东西。

(虽然有时可能会在这里看到“抽象泄漏”;例如,使用引用类型声明的类成员几乎必须占用存储空间,并且将在我所知道的每个 ABI 中实现为指针。这只是一个实际需要。)

计算机程序

在这里,我的意思是由您的编译器创建的实际计算机程序。它包含目标机器将执行的实际指令。

在该实际的程序中,对于任何存取,有可能或可能不是一个指针的间接引用,并且可以存在或可能甚至不存储在存储器中的某些地方的对象。相反,该值可能只是嵌入到您的代码中。有些人称之为“优化”,但实际上只是您的编译器生成了具有您描述的语义的最佳计算机程序。

这既适用于非引用也适用于引用。例如,在任何体面的“优化”级别,您的整个真实程序可能只是将整数发送20std::cout机器的代码;int在执行期间,这些s没有理由作为对象在任何内存位置实际“存在”,因为您永远不会获取它们的地址或将所述地址传递给其他需要通过链接器的魔法“共享”它们的翻译单元.

因此,如果您真的很关心性能,则需要阅读汇编代码以了解实际发生的情况。否则,你不能也不需要预测它。

把它们放在一起……

...没有真正的理由担心您的引用本身是别名还是“变量”,因为编译过程已经完全模糊了这种区别。