![5f74874fca5fbd08c223e6c0ebd6807d.png](https://i-blog.csdnimg.cn/blog_migrate/c16ce21042eff98cd578370cc560bedb.jpeg)
Python的对象引用
众所周知,Python里的大部分对象都是存在堆上,变量名只是对堆上数据的引用,因此可以很轻易地对变量所指向的对象进行替换,如:
# 引用替换
v = object_A
if condition:
v = object_b
change(v)
同时,Python的参数传递也是传对象引用(pass-by-object-reference),也就是把对象的指针传过去,如:
# 传对象引用
def change(nums):
nums.append(1)
v = []
change(v)
assert len(v) == 1
以上两点在Python中让我们代码开发变得高效简洁,但是在C++中却没有这么好的特性。因此就引入C++ functional库中的reference_wrapper来让C++也能像Python这样简单地进行对象引用以及对象引用的替换。
在正式介绍reference_wrapper前, 先来看看C++中如何实现上述两个操作。
C++引用替换
如果我们把Python的引用替换代码直接翻译成C++,那显然是行不通的,如下:
auto& v = object_A
if (condition) {
v = object_B
assert (&v != &object_B); // assertion fail
}
change(v);
因为在C++中,对引用赋值与对原始对象赋值一样,并不会改变引用所指向对象的地址(不会把v指向的对象从object_A变成object_B),而只会改变所指向对象的值(如果能赋值成功的话,等同于object_A=object_B)。这是因为C++的引用只能被绑定一次,之后的赋值都是对对被绑定对象赋值(assign-through)。
如果想要在C++中实现引用替换的话,有多种变通方法。首先我们可以想到用lambda匿名函数来判断如何对这个引用变量赋值:
auto& v = [&]() -> auto& {
return condition ? object_B : object_A; }();
change(v);
这个方法虽然可以较为简单实现引用替换,但这不适用与逻辑相对复杂的情况,如先用指向object_A的v进行一系列操作,再把v指向另一个地方进行更多操作。而且也降低了代码的可读性。
当然我们也可以直接用原始的指针来实现:
auto* v = &object_A;
if (condition)
v = &object_B;
change(*v)