书中说:因为引用不是对象,所以我们可能没有定义对引用的引用。
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的初始值。
这很有道理,但如果这不是对引用的引用的定义,那么当它提到“因为引用不是对象时,我们可能无法定义对引用的引用”这本书究竟是什么意思。 ??
有人可能会举个例子吗?
答案 0 :(得分:5)
您的理解是正确的。
int &refVal3 = refVal;
这使得refVal3
对同一事物的引用refVal
是对它的引用。也就是ival
。
这本书在提到“因为 引用不是对象,我们可能没有定义对a的引用 参考。“?
引用只能引用一个对象。但引用不是对象。所以引用不能引用参考。当这本书说明这一点时,它并不仅仅意味着它不被允许,如果你尝试,你会得到一个错误。但你甚至无法尝试。它没有语法。因为你试图对引用做的任何事情,你实际上将对它引用的对象做,而不是对引用本身。
有人可能会举个例子吗?
没有。我不能。这就是重点。根本就没有语法。
答案 1 :(得分:1)
T & &
)。其中T
是对象类型(包括int
,如您的示例所示):
您可以(lvalue) references到T
。存在类型T &
。
您可以rvalue references到T
。存在a type T &&
T &&
是not a reference to a reference; &&
是single token,并不代表& &
。
您无法引用对T
的引用。有<{1}},T & &
,T & &&
或T && &
没有此类型。如果您编写了一个尝试显式命名此类型的声明,则这是一个错误。
(同样,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,我得到:
错误:&#39; refRefVal&#39;声明为对引用的引用
其他编译器也会出现类似的错误。例如,Microsoft Visual C++ gives:
错误C2529:&#39; refRefVal&#39;:引用参考是非法的
引用在它们出现的大多数上下文中自动解除引用。你尝试对引用做的任何事情,实际上你正在对它引用的对象做这件事。与指针不同,没有用于取消引用引用的运算符;实际上,引用是引用对象的名称。
您所写的内容(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 ++语言根本就没有这种类型。