我试图掌握C++引用的窍门(我想我已经在Java和Javascript中掌握了它,但过渡比我想象的要困难(。这是一狙击代码,其结果我不明白:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> x;
x.push_back(1);
std::vector<int> y;
y.push_back(2);
std::vector<int>& r=x;
r.push_back(3);
std::vector<int>& s=r;
s.push_back(4);
s=y;
r.push_back(5);
s.push_back(6);
std::cout<<"x: ";
for(int i: x) {std::cout<< i<< " ";} std::cout<<"n";
std::cout<<"y: ";
for(int i: y) {std::cout<< i<< " ";} std::cout<<"n";
}
我得到以下输出(使用 g++ 4.9.2(:
x: 2 5 6
y: 2
我不明白这一点:元素 1、3、4 变成了什么?我本来期望 x 是 1,3,4,5,y 是 2,6。拥有整数向量的事实会有所不同吗?
重要的一点:引用是不可恢复的。初始化引用后,它将始终引用同一对象。
现在让我们一步一步地分析你的代码:
std::vector<int> x;
x.push_back(1);
x
是一个包含 1
的向量。
std::vector<int> y;
y.push_back(2);
y
是一个包含 2
的向量。
std::vector<int>& r=x;
r.push_back(3);
r
是对x
的引用,现在包含1 3
。
std::vector<int>& s=r;
s.push_back(4);
s
是对x
的引用,现在包含1 3 4
。
s=y;
现在,您已将向量y
复制到向量x
(通过引用它的引用s
(。这会用y
的内容替换x
的内容,即2
。
r.push_back(5);
s.push_back(6);
x
(r
和s
都引用(现在包含2 5 6
。
y
在创建后的单push_back
之后从未被修改过,因此它只包含2
.
Java称之为"引用"的概念实际上是"指针"在C++中的含义。使用指针,代码将如下所示:
std::vector<int>* r = &x;
r->push_back(3);
std::vector<int>* s = r;
s->push_back(4);
s = &y;
r->push_back(5);
s->push_back(6);
然后,x
将包含1 3 4 5
,y
将包含2 6
。
请注意,创建指向对象的指针(获取对象的地址(的语法需要显式使用 address-of 运算符 &
。同样,取消引用指针需要显式语法:*p
用于简单地获取指向的对象,p->m
用于访问p
指向的对象的成员m
。
引用绑定到对象一次,并且永远不能重新拔插。根本没有语法。正如您在使用例如 s.push_back
,每当您命名s
时,您都会访问所指r
(通过扩展,实际上是x
(。
因此,s=y
不会使引用引用另一个向量。你在这里做的事情和x=y
一样。最初在x
中的所有元素都丢失了。
与 C++ 中的引用语义的关系几乎为零。你最好立即停止试图比较两者,或者从一个"过渡"到另一个。带着干净、清新的头脑来到C++。
赋值s=y;
其中s
引用x
,导致将y
复制到覆盖 (1,3,4( 的x
。所以x
变成 (2(,然后附加 5 和 6。与此同时,y
保持不变,最终(2(。