(点击上方公众号,可快速关注)
前段时间解决了一个关于引用的bug,原因是引用“重新赋值”造成的,原来的代码逻辑关于队列的选择,为了凸显问题,这里使用一个简单的例子重写。示例代码如下:
int a = 1;
int b = 2;
// 默认取a
int& c = a;
// 若满足某种条件,取b
c = b;
从代码注释可以看出来,这段代码希望实现的效果是:引用c
可以根据条件选择指向的变量。但代码实际的执行效果是却是:c
是a
的别名,两者等同,然后c = b;
将b
的值赋给了c
和a
,所以最后c
的值为2。
之所以出现这个问题还是基础不牢,忘了最基本的一点:引用只能在初始化的时候赋值,后续的赋值实际上修改的都是引用指向的对象。
其实我觉得还有个另外一个原因导致了这种混淆,在于C++中的引用的初始化是隐式的,上面代码c
右侧的a
和b
都是变量,我们从=
右侧看不出操作的结果,只能综合结合左侧做出判断。类比一下C/C++中指针的初始化:
int a = 0;
int* c = &a;
可以看到指针的初始化要简单的多,我们通过=
右侧的&a
就可以判断出这个操作是将a
的地址赋给c
。这种语法的不一致也导致很多人对&
符号到底是取地址符还是引用傻傻分不清,复用已有的关键字和符号还是有很多心智负担的。Rust的引用相对好区分:
let x = 10;
let r = &x;