过去几个月我一直在学习C ++。我知道函数你的第一个声明参数如下:
int myFunc(int funcVar);
然后您可以将整数变量传递给该函数,如下所示:
int x = 5;
myFunc(x);
将参数传递给函数时,我通常会想到将x的值分配并复制到myFunc的参数中,这在C ++中看起来像这样:
funcVar = x;
但是,当我声明具有引用(或指针)参数的函数时,我注意到了:
int myFunc(int & funcVar);
我可以将变量x传递给myFunc:
myFunc(x);
看起来像(在我看来):
&funcVar = x;
或者您可以传入实际引用作为参数
int & rX = x;
myFunc(rX);
并且该函数也可以正常工作,我的想法看起来像C ++中的这个语句
int & funcVar = rX
分配对引用的引用是没有意义的。我的问题是编译器如何实际加载函数中的参数?我不应该想到将变量的值赋值给函数的参数吗?
答案 0 :(得分:1)
当你调用一个函数时,函数的每个参数都是初始化(未分配)。其规则与任何其他复制初始化的规则相同。所以,如果你有
funcVar
然后int funcVar = x;
被初始化,好像是这样的语句:
int myFunc(int & funcVar);
myFunc(x);
int & rX = x;
myFunc(rX);
如果你有
funcVar
然后int & funcVar = x;
int & funcVar = rX;
被初始化(以及未分配),就好像这样的语句:
rX
引用的初始化将其绑定到初始化程序表示的对象或函数。第二次初始化确实有意义--- 表达式 x
表示对象 rX
,因为x
是绑定到rX
的引用{1}}。因此,使用x
初始化引用与使用{{1}}初始化引用具有相同的效果。
答案 1 :(得分:1)
让我们轻松编写代码并进行反汇编。
int by_value(int x) { return x; }
int by_reference(int &x) { return x; }
int by_pointer(int *x) { return *x; }
int main()
{
int x = 1;
by_value(x);
by_reference(x);
by_pointer(&x);
return 0;
}
$ g++ -g -O0 a.cpp ; objdump -dS a.out
在我的环境(x86_64,g ++(SUSE Linux)4.8.3 20140627)中,结果如下。 (全文在这里http://ideone.com/Z5G8yz)
00000000004005dd <_Z8by_valuei>:
int by_value(int x) { return x; }
4005dd: 55 push %rbp
4005de: 48 89 e5 mov %rsp,%rbp
4005e1: 89 7d fc mov %edi,-0x4(%rbp)
4005e4: 8b 45 fc mov -0x4(%rbp),%eax
4005e7: 5d pop %rbp
4005e8: c3 retq
00000000004005e9 <_Z12by_referenceRi>:
int by_reference(int &x) { return x; }
4005e9: 55 push %rbp
4005ea: 48 89 e5 mov %rsp,%rbp
4005ed: 48 89 7d f8 mov %rdi,-0x8(%rbp)
4005f1: 48 8b 45 f8 mov -0x8(%rbp),%rax
4005f5: 8b 00 mov (%rax),%eax
4005f7: 5d pop %rbp
4005f8: c3 retq
00000000004005f9 <_Z10by_pointerPi>:
int by_pointer(int *x) { return *x; }
4005f9: 55 push %rbp
4005fa: 48 89 e5 mov %rsp,%rbp
4005fd: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400601: 48 8b 45 f8 mov -0x8(%rbp),%rax
400605: 8b 00 mov (%rax),%eax
400607: 5d pop %rbp
400608: c3 retq
0000000000400609 <main>:
int main()
{
400609: 55 push %rbp
40060a: 48 89 e5 mov %rsp,%rbp
40060d: 48 83 ec 10 sub $0x10,%rsp
int x = 1;
400611: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp)
by_value(x);
400618: 8b 45 fc mov -0x4(%rbp),%eax
40061b: 89 c7 mov %eax,%edi
40061d: e8 bb ff ff ff callq 4005dd <_Z8by_valuei>
by_reference(x);
400622: 48 8d 45 fc lea -0x4(%rbp),%rax
400626: 48 89 c7 mov %rax,%rdi
400629: e8 bb ff ff ff callq 4005e9 <_Z12by_referenceRi>
by_pointer(&x);
40062e: 48 8d 45 fc lea -0x4(%rbp),%rax
400632: 48 89 c7 mov %rax,%rdi
400635: e8 bf ff ff ff callq 4005f9 <_Z10by_pointerPi>
return 0;
40063a: b8 00 00 00 00 mov $0x0,%eax
}
by_reference(x)与by_pointer(&amp; x)相同!
答案 2 :(得分:0)
将引用分配给另一个引用(首次定义它时,即在初始化时)以及实际发生的事情是非常有意义的。引用只是一个别名,因此当您为另一个引用分配引用时,您只是说第一个引用是您指定的引用的别名。实施例
int x = 42;
int& rx = x;
int& ry = rx;
++ry;
std::cout << x; // displays 43