不确定有关C ++ Primer中的Reference的描述

时间:2017-07-25 03:41:11

标签: c++

书中说:因为引用不是对象,所以我们可能没有定义对引用的引用。

int ival = 1024;
int &refVal = ival;
refVal = 2;
int ii = refVal;
int &refVal3 = refVal; // isn't this a definition of ref to ref?
int i = refVal;
int &refVal4 = 10;
double dval = 3.14;
int &refVal5 = dval;

但是,该行不是错误,因为refVal3说它只是refVal的另一个别名,而refVal只是ival的另一个名称(refVal3绑定到refVal绑定的对象,即ival) ...所以refVal和refVal3都引用了ival的初始值。

这很有道理,但如果这不是对引用的引用的定义,那么当它提到“因为引用不是对象时,我们可能无法定义对引用的引用”这本书究竟是什么意思。 ??

有人可能会举个例子吗?

2 个答案:

答案 0 :(得分:5)

您的理解是正确的。

int &refVal3 = refVal;

这使得refVal3对同一事物的引用refVal是对它的引用。也就是ival

  

这本书在提到“因为   引用不是对象,我们可能没有定义对a的引用   参考。“?

引用只能引用一个对象。但引用不是对象。所以引用不能引用参考。当这本书说明这一点时,它并不仅仅意味着它不被允许,如果你尝试,你会得到一个错误。但你甚至无法尝试。它没有语法。因为你试图对引用做的任何事情,你实际上将对它引用的对象做,而不是对引用本身。

  

有人可能会举个例子吗?

没有。我不能。这就是重点。根本就没有语法。

答案 1 :(得分:1)

C ++中不存在引用类型(如T & &)。

其中T是对象类型(包括int,如您的示例所示):

(同样,cv-qualified类型like const T&存在,而T && &&等类型则不存在。)

你问了一个例子。考虑这个错误的代码:

const T & &

这是一个错误,因为没有int main() { int ival = 1024; int &refVal = ival; int & &refRefVal = refVal; // wrong } 这样的类型。无论我试图用它来初始化它都是错误的。

(严格来说,这是一个错误,因为该语言的语法禁止它。标准委员会可以选择允许我写int & &并让它意味着同样的事情如int & & - 请参阅下面的参考折叠 - 但他们没有,这很好,因为这会非常令人困惑。)

When I attempt to compile that wrong code与Clang 3.8,我得到:

  

错误:' refRefVal'声明为对引用的引用

其他编译器也会出现类似的错误。例如,Microsoft Visual C++ gives

  

错误C2529:' refRefVal':引用参考是非法的

使用引用时,效果是使用它引用的对象。

引用在它们出现的大多数上下文中自动解除引用。你尝试对引用做的任何事情,实际上你正在对它引用的对象做这件事。与指针不同,没有用于取消引用引用的运算符;实际上,引用是引用对象的名称。

您所写的内容(int &)不是错误,因为您只是初始化绑定到同一对象的第二个引用。要了解这是为什么,请考虑几个陈述的影响。

在此创建int &refVal3 = refVal;,使用值int初始化它:

1024

在这里你制作一个左值引用,绑定到int ival = 1024; 个对象:

int

在此您将int &refVal = ival; 分配给原始2对象,因为int用作其引用的对象:

refVal

在这里,您创建了第二个refVal = 2; 对象,使用原始对象的值进行初始化,同时因为int被用作它所引用的对象:

refVal

在这里你对原始对象进行第二次左值引用,也因为int ii = refVal; 被用作它所引用的对象:

refVal

看起来像它创建对第一个引用的第二个引用的代码实际上是在创建对原始对象的第二个引用。

这就是说int &refVal3 = refVal; 引入另一个对原始对象的引用 - 而不是试图创建对引用的引用 - 的原因是只是{{1>的另一个结果被自动理解为int &refVal3 = refVal;指的是

参考折叠

您不能自己编写名为refVal的类型,但是这个呢?

int

这会导致编译器看到我正在尝试将类型别名T & &设为using Ref = int&; using RefRef = Ref&; // I named this poorly, it's not really a reference to a reference! 。编译器遵循the rules of reference collapsing。它将两个引用合并为一个,因此效果与我写的相同:

RefRef

此行为在涉及类型推导的情况下非常有用,例如templates,通过允许更多代码按预期编译和工作,以及facilitating perfect forwarding。 (有人可能认为它也与您观察到的相似 - 当您从引用初始化引用时,您仍然无法获得引用引用,只能引用对象。)

在任何情况下都没有任何类型引用参考的东西。 C ++语言根本就没有这种类型。