自相矛盾的引用定义

Contradicting definition of references

我正在学习 C++ 中的引用。特别是,我了解到引用不是实际对象。相反,他们指的是其他一些对象。也就是说,引用只是其他对象的别名。

然后我遇到了 this 上面写着:

Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object, just with another name. It is neither a pointer to the object, nor a copy of the object. It is the object. There is no C++ syntax that lets you operate on the reference itself separate from the object to which it refers.

我明白上面的引述意味着我们不能对引用本身进行操作,与它所引用的对象分开,但它仍然似乎暗示“一个引用是一个对象。

此外,我遇到了下面给出的句子:

In ISO C++, a reference is not an object. As such, it needs not have any memory representation.

我没有第二个引述的 link,但我在某个 SO 的 post 某处读到了它。

我的问题是,假设第二个引用也来自标准(可能不是这种情况),这两个引用的语句是否相互矛盾。或者至少第一句话是误导性的。哪一个是正确的。

我目前的理解(通过阅读 C++ Primer 第 5 版等书籍)是引用是对象的别名。这让我想到他们不应该在内存中使用任何 space。

第一条引述实际上是在说引用与对象不可分离。

... still seems to imply that "a reference is an object".

这实际上意味着引用是对象的 non-separable、non-first-class 别名,正如您最初所说的那样。

这些讨论的困难在于,“对象”的标准含义已经不同于大多数 less-formal 上下文中使用的含义。

让我们从简单的开始:

int a;

通常会被描述为声明一个整数对象 a,对吧?实际上

  1. 声明一个整数对象
  2. 将名称 a 绑定到适当范围内的对象

现在,如果我们写

int &b = a;

我们可以说 b 对象,就像我们可以说 a 是对象一样。实际上两者都不正确,但考虑到非正式文本已经使用了后者,它并不 更糟

我们应该说名称 b 与名称 a 指的是同一个对象。这与称它为别名完全一致,但非正式或介绍性的文本如果在任何地方都写“......由名称 a 引用的整数对象......”而不仅仅是“整数”,看起来会很麻烦a".

至于在内存中使用 space ......这取决于。如果我在单个函数中为单个对象引入 100 个别名,如果编译器不只是折叠它们(当然它们可能仍会显示在调试符号中),我会感到非常惊讶。省略冗余名称不会丢失任何信息。

如果我通过对 non-inlined 函数的引用传递参数,一些 实际信息正在传达,并且该信息必须存储在某处。

Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object, just with another name. ...

注释是非正式的,通常不应被解释为严格的规则。如果解释与标准规则相矛盾,则该解释是错误的。

引用和对象是不同种类的实体。引用不是与其命名的对象不同的对象。不可能形成指向引用的指针。 “指向引用的指针”甚至不是有效的类型类别。

注释试图说明引用“是”它所命名的对象,即使用引用就是使用被引用的对象。

I was thinking of confirming that whether or not references take any space

参考文献采用 space 或不采用 space。由语言实现来确定在每种情况下是否需要 space。

标准报价:

[dcl.ref] It is unspecified whether or not a reference requires storage


在标准规范之外,如果您想要使用 space 的引用示例,请尝试将引用成员添加到 class,您很可能会观察到 class增加。

since pointers take space then reference should also take space. ...

指针确实在标准指定的抽象机中使用 space。但是,如果您从不观察存储,那么存储实际上根本不存在是完全可能的。引用和指针之间的显着区别是您无法直接观察引用的存储。

哲学家:“如果一棵树倒在一台抽象机器中,而周围没有人观察它,它有影响吗

优化者:“如果我能帮上忙就不会。”

引用实际上“是”什么并没有多大意义:您可以说它是被引用的对象或者它是它的别名,这些说法在某种意义上都是正确的。

int main()
{
    int a(0);
    int& ref(a);

    ref = 1; // Will actually affect the value of a

    return 0;
}

让我们逐行分析这个程序。

  • int a(0); 在堆栈上分配一些内存(通常是 4 个字节)来保存一个整数。
  • int& ref(a); 不一定分配内存,不管它是否真的会分配内存compiler-specific。从这个意义上说,ref 本身不是一个对象:它只是 a 的一个别名,另一个名称。这就是第二个引用“引用不是对象”的意思。 (请注意,有时,当无法知道在 compile-time 处引用了什么对象时,引用必须为对象的地址保留额外的 space 。在这些情况下,引用只是语法指点糖。)
  • ref = 1;a 的值设置为 1。从这个意义上说,您可以将 ref 视为与 a 完全相同的对象。 任何“对”引用的操作实际上都会对引用的对象进行操作。这就是第一个引号“它是对象”的意思。

引用提供了另一种引用对象的方式。这在将参数 by reference 传递给函数时特别有用。更正式地说,引用是绑定到 变量 别名 ,在这种情况下,包括 匿名临时 [=26] =].

幸运的是我们不需要关心它们是如何实现的。这是编译器的工作,而且技术各不相同。 C++标准不要求它们占用任何内存。

这里顺便说一句区分引用类型的方法。 Non-separability 实际上更多的是关于不能将引用绑定到任何其他变量。参见

#include <iostream>
#include <type_traits>

int main() {
    int a = 0;
    int& ref = a;
    std::cout << (
        std::is_reference<decltype(ref)>::value ? "pay me a bonus\n" : "reformat my hard disk\n"
    );
    std::cout << (
        std::is_reference<decltype(a)>::value ? "pay me a bonus\n" : "reformat my hard disk\n"
    );
}

最后请注意,&a&ref 必须始终相同。