代码如:
// 'type' here indicates certain variable type, int, char, struct, etc.
void foo(type &a, type b) {...}
type a = ...;
type b = ...;
type &c = a;
foo(a, b);
foo(c, b);
编译没有问题。但从字面上看,foo
的第一个参数是type&
是参考,foo(c, b)
看起来比foo(a, b)
更加一致,因为c
是参考type&
本身,a
只有type
个变量。
例如说void bar(int*)
和int *a; int b
由于参数类型不同,只能将a
传递给bar
而不是b
。
通过参考案例传递这种不一致的底层机制是什么?
答案 0 :(得分:1)
引用通常仅实现为指向内存地址的指针。将变量分配给引用会分配变量的内存地址。分配对引用的引用会复制内存地址。如果您将引用视为一个指针(逻辑上就是这样,只需要额外的编译器强制限制),您的示例代码基本上就是执行以下操作:
void foo(type *a, type b) {...}
type a = ...;
type b = ...;
type *c = &a;
foo(&a, b);
foo(c, b);
答案 1 :(得分:0)
在您的示例中,a
的类型为type
,因此b
。 c
的类型为type&
。
当您通过传递a
作为第一个参数来调用该函数时,它会抓取您对a
副本的引用。当您使用c
作为参数调用它时,由于c
已经是引用,因此它不必引用,因为它已经是引用。
过去引用有一些差异,但现在主要只是比指针更方便的语法。使用指针,您的示例如下所示:
void foo(type *a,type b) {...}
type a = ...;
type b = ...;
type *c = &a;
foo(&a, b); // the compiler is really doing this for you when you use references
foo(c, b);
仅差异(在现代编译器上)是编译器为您执行引用和解除引用,并且不让指针为空(除非你做了创造性的事情,你将不会这样做)。
如果有助于在语言上考虑它,您的功能是说“请给我一个type
实例的引用和type
实例的副本。”
您的第一个电话是“在这里,获取对此type
实例的引用,此处是此另一个type
实例的副本。”
你的第二个电话是“在这里,抓住这个对type
实例的引用,这里是另一个type
实例的副本。”
答案 2 :(得分:0)
您正在混淆变量的声明及其用法。
后:
type a = x;
type &c = a;
情况与您写完的情况完全相同:
type c = x;
type &a = c;
在这两种情况下,都有一个变量,它有两个名称,a
和c
。
由于C ++ 11存在一个区别,decltype(a)
将选择引用作为类型的一部分
此后在表达式中使用a
或c
时,它会引用该变量。
当您void foo(type &p, type q)
(更改名称以避免混淆)时,如果您致电foo(a, b);
,则名称p
将成为参数a
的另一个名称。有一个对象有两个名称a
(对调用者可见)和p
(在函数中可见)。
后一种情况通常由编译器以与实现指针传递相同的方式实现(但实现细节不是在形成某种意义的心理模型时应该考虑的事项。)