![dbf53c612572a68d0d8e64e8d5aeca7b.gif](https://i-blog.csdnimg.cn/blog_migrate/cb98b5c6dce78486c97c92e1732fb5ea.gif)
作者 | 樱雨楼
![ff105d953e83637ef928ef80419a72ec.png](https://i-blog.csdnimg.cn/blog_migrate/6b14df8630776be4132d8d5299fdcbb3.png)
![0cf74bc23f4db44a679c22703d290efc.png](https://i-blog.csdnimg.cn/blog_migrate/80c00d667f3833c4985bfa42f42ac1bc.png)
承载通过 malloc、new、allocator 等获取的动态内存
使得 pass-by-pointer 成为可能
避免对实参无意义的值拷贝,大幅提高效率
使得对某个变量的修改能力不局限于变量自身的作用域
使得 swap、移动构造函数、移动赋值运算等操作可以仅针对数据结构内部的指针进行操作,从而避免了对临时对象、移后源等对象的整体内存操作
![5f6d72ded68be8bfcb0461fbbe7dff06.png](https://i-blog.csdnimg.cn/blog_migrate/3acabcd1eacb88c29fd3237d09b2a1f5.png)
int numA = 0, &lrefA = numA; // Binding an lvalue
cout <endl; // Use the lvalue reference as lvalue & rvalue
decltype(lrefA) numB = 1; // Error!
左值引用常用于 pass-by-reference:
void swap(int &numA, int &numB){
int tmpNum = numA;
numA = numB;
numB = tmpNum;
}
int main(){
int numA = 1, numB = 2;
swap(numA, numB);
cout <endl <endl; // 2 1
}
右值引用
右值引用于其初始化阶段绑定到右值,其常用于移动构造函数和移动赋值操作。在这些场合中,移动构造函数和移动赋值操作通过右值引用接管被移动对象。
右值引用与本文内容无关,故这里不再详述。
![c751da242402ef975293436c02182fcd.png](https://i-blog.csdnimg.cn/blog_migrate/f76164c5b9f76af8539e3045f18fc55a.png)
在任何情况下(包括赋值、实参传递等)均不存在显式值拷贝,当此种情况发生时,只增加了一次引用计数
变量可以进行重绑定(对应于一个不含顶层 const(top-level const)的指针)
在某些情况下(下文将对此问题进行详细讨论),可通过函数实参修改原值
sampleNum = 0
其不类似于 C++ 代码:
int sampleNum = 0;
而更类似于:
int __tmpNum = 0, *sampleNum = &__tmpNum;
// 或者:
shared_ptr<int> sampleNum(new int(0));
__setitems__操作将隐式解指针
Python与指针的另一个重要联系在于 Python 的隐式解指针行为。
虽然 Python 不存在显式解指针操作,但(有且仅有)__setitems__操作将进行隐式解指针,通过此方法对变量进行修改等同于通过解指针操作修改变量原值。
此种性质意味着:
1. 任何不涉及__setitems__的操作都将成为指针重绑定。
对于Python代码:
numList = [None] * 10
# Rebinding
numList = [None] * 5
其相当于:
int *numList = new int[10];
// Rebinding
delete[] numList;
numList = new int[5];
delete[] numList;
由此可见,对 numList 的非__setitems__操作,导致 numList 被绑定到了一个新指针上。
2. 任何涉及__setitems__的操作都将成为解指针操作。
由于 Python 对哈希表的高度依赖,“涉及__setitems__的操作”在 Python 中实际上是一个非常广泛的行为,这主要包括:
对数组的索引操作
对哈希表的查找操作
涉及__setattr__的操作(由于 Python 将 attribute 存储在哈希表中,所以__setattr__操作最终将是某种__setitems__操作)
class Complex(object):
def __init__(self, real = 0., imag = 0.):
self.real = real
self.imag = imag
def __repr__(self):
return '(%.2f, %.2f)' % (self.real, self.imag)
def main():
complexObj = Complex(1., 2.)
complexObj.real += 1
complexObj.imag += 1
# (2.00, 3.00)
print(complexObj)
if __name__ == '__main__':
main()
class Complex
{
public:
double real, imag;
Complex(double _real = 0., double _imag = 0.): real(_real), imag(_imag) {}
};
ostream &operator<const Complex &complexObj)
{
return os <"(" <", " <")";
}
int main(){
Complex *complexObj = new Complex(1., 2.);
complexObj->real++;
complexObj->imag++;
cout <endl;
delete complexObj;
return 0;
}
由此可见,无论是 int、float 这种简单的 Python 类型,还是我们自定义的类,其构造行为都类似使用 new 构造对象并返回指针。
且在 Python 中任何涉及“.”和“[]”的操作,都类似于对指针的“->”或“*”解指针操作。
![3d65080d4242d27f98528bfe4ae2b6b6.png](https://i-blog.csdnimg.cn/blog_migrate/3a3e4f307dd4f811cf56033dd2f32f3b.png)
【END】
热 文 推 荐
☞三大运营商回复 4G 降速;微信上线语音转文字功能;IntelliJ IDEA 2019.2.1 发布 | 极客头条
☞程序员为什么需要框架?
☞ 细数微软 Teams 的 14 宗“罪”!
☞ 华为暂没有推出鸿蒙手机计划;苹果否认 iPhone 辐射超标;Kotlin 1.3.50 发布 | 极客头条
☞ 我是如何通过开源项目月入 10 万的?
☞ 深度 | 语音识别技术简史:从不温不火到炙手可热 ☞ 意大利黑手党四大家族做了条"犯罪链", 把家族的权利被分的明明白白的…… ☞ Istio 庖丁解牛六:多集群网格应用场景 ☞ 如何写出让同事无法维护的代码?
你点的每个“在看”,我都认真当成了喜欢