对比 C++ 和 Python,谈谈指针与引用

花下猫语:本文是学习群内 樱雨楼 小姐姐的投稿。之前已发布过她的一篇作品《当谈论迭代器时,我谈些什么?》,大受好评。本文依然是对比 C++ 与 Python,来探讨编程语言中极其重要的概念。祝大家读有所获,学有所成!

68b02e3bly1g4xcd8e8sqj21g80yl41g.jpg

樱雨楼 | 原创作者

豌豆花下猫 | 编辑润色

本文原创并首发于公众号【Python猫】,未经授权,请勿转载。

原文地址:https://mp.weixin.qq.com/s/k0VNL6uyvBHT7PWdzEPROQ

0 引言

指针(Pointer)是 C、C++ 以及 Java、Go 等语言的一个非常核心且重要的概念,而引用(Reference)是在指针的基础上构建出的一个同样重要的概念。

指针对于任何一个编程语言而言都是必须且重要的,虽然 Python 对指针这一概念进行了刻意的模糊与限制,但指针对于 Python 而言依然是一个必须进行深入讨论的话题。

本文基于 C++ 与 Python,讨论了 Python 中与指针及引用相关的一些行为。

68b02e3bly1g4xc5k233pg20b405w4mc.gif

1 什么是指针?为什么需要指针?

指针有两重含义:

(1)指代某种数据类型的指针类型,如整形指针类型、指针指针类型

(2)指代一类存放有内存地址的变量,即指针变量

指针的这两重含义是紧密联系的:作为一种变量,通过指针可以获取某个内存地址,从而为访问此地址上的值做好了准备;作为一种类型,其决定了内存地址的正确偏移长度,其应等于当前类型的单位内存大小。

如果一个指针缺少指针类型,即 void *,则显然,其虽然保存了内存地址,但这仅仅是一个起点地址,指针会因为无法获知从起点向后进行的偏移量,从而拒绝解指针操作;而如果一个指针缺少地址,即 nullptr,则其根本无法读取特定位置的内存。

指针存在的意义主要有以下几点:

  • 承载通过 malloc、new、allocator 等获取的动态内存
  • 使得 pass-by-pointer 成为可能

pass-by-pointer 的好处包括但不限于:

  • 避免对实参无意义的值拷贝,大幅提高效率
  • 使得对某个变量的修改能力不局限于变量自身的作用域
  • 使得 swap、移动构造函数、移动赋值运算等操作可以仅针对数据结构内部的指针进行操作,从而避免了对临时对象、移后源等对象的整体内存操作

由此可见,与指针相关的各操作对于编程而言都是必须的或十分重要的。

68b02e3bly1g4xc6ogkvtj20sg0f4755.jpg

2 C++中的引用

在 C++ 中,引用具有与指针相似的性质,但更加隐形与严格。C++ 的引用分为以下两种:

2.1 左值引用

左值引用于其初始化阶段绑定到左值,且不存在重新绑定。

左值引用具有与被绑定左值几乎一样的性质,其唯一的区别在于 decltype 声明:

int numA = 0, &lrefA = numA;  // Binding an lvalue
cout << ++lrefA << 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 << numA << endl << numB << endl;  // 2 1
}

2.2 右值引用

右值引用于其初始化阶段绑定到右值,其常用于移动构造函数和移动赋值操作。在这些场合中,移动构造函数和移动赋值操作通过右值引用接管被移动对象。

右值引用与本文内容无关,故这里不再详述。

3 Python中的引用

3.1 Python不存在引用

由上文讨论可知,虽然“引用”对于 Python 而言是一个非常常用的术语,但这显然是不准确的——由于 Python 不存在对左/右值的绑定操作,故不存在左值引用,更不存在右值引用。

3.2 Python的指针操作

不难发现,虽然 Python 没有引用,但其变量的行为和指针的行为具有高度的相似性,这主要体现在以下方面:

  • 在任何情况下(包括赋值、实参传递等)均不存在显式值拷贝,当此种情况发生时,只增加了一次引用计数
  • 变量可以进行重绑定(对应于一个不含顶层 const(top-level const)的指针)
  • 在某些情况下(下文将对此问题进行详细讨论),可通过函数实参修改原值

由此可见,Python 变量更类似于(某种残缺的)指针变量,而不是引用变量。

68b02e3bly1g4xc891rijj21hc0swjux.jpg

3.2.1 构造函数返回指针

对于 Python 的描述,有一句非常常见的话:“一切皆对象”。

但在这句话中,有一个很重要的事实常常被人们忽略:对象是一个值,不是一个指针或引用。

所以,这句话的准确描述应该更正为:“一切皆(某种残缺的)指针”。虽然修改后的描述很抽象,但这是更准确的。

而由于对象从构造函数而来,至此我们可知:Python 的构造函数将构造匿名对象,且返回此对象的一个指针。

这是 Python 与指针的第一个重要联系。

用代码描述,对于Python代码:

sampleNum = 0

其不类似于 C++ 代码:

int sampleNum = 0;

而更类似于:

int __tmpNum = 0, *sampleNum = &__tmpNum;// 或者:
shared_ptr<int> sampleNum(new int(0));

3.2.2 __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 被绑定到了一个新指针上。

  1. 任何涉及__setitems__的操作都将成为解指针操作。

由于 Python 对哈希表的高度依赖,“涉及__setitems__的操作”在 Python 中实际上是一个非常广泛的行为,这主要包括:

  • 对数组的索引操作
  • 对哈希表的查找操作
  • 涉及__setattr__的操作(由于 Python 将 attribute 存储在哈希表中,所以__setattr__操作最终将是某种__setitems__操作)

我们用一个稍复杂的例子说明这一点:

对于以下Python代码:

class Complex(object):def __init__(self, real = 0., imag = 0.):self.real = realself.imag = imagdef __repr__(self):return '(%.2f, %.2f)' % (self.real, self.imag)def main():complexObj = Complex(1., 2.)complexObj.real += 1complexObj.imag += 1# (2.00, 3.00)print(complexObj)if __name__ == '__main__':main()

68b02e3bly1g4xcaddxjbg20b405zqv5.gif

其相当于:

class Complex
{
public:double real, imag;Complex(double _real = 0., double _imag = 0.): real(_real), imag(_imag) {}
};ostream &operator<<(ostream &os, const Complex &complexObj)
{return os << "(" << complexObj.real << ", " << complexObj.imag << ")";
}int main()
{Complex *complexObj = new Complex(1., 2.);complexObj->real++;complexObj->imag++;cout << *complexObj << endl;delete complexObj;return 0;
}

由此可见,无论是 int、float 这种简单的 Python 类型,还是我们自定义的类,其构造行为都类似使用 new 构造对象并返回指针。

且在 Python 中任何涉及“.”和“[]”的操作,都类似于对指针的“->”或“*”解指针操作。

4 后记

本文探讨了 Python 变量与指针、引用两大概念之间的关系,主要论证了“Python 不存在引用 ”以及“Python 变量的行为类似于某种残缺的指针 ”两个论点。

所有论点均系作者个人观点,如有错误,恭迎指正。

68b02e3bly1g2aiq1kpa8j21hc0nmgs4.jpg

公众号【Python猫】, 本号连载优质的系列文章,有喵星哲学猫系列、Python进阶系列、好书推荐系列、技术写作、优质英文推荐与翻译等等,欢迎关注哦。

转载于:https://www.cnblogs.com/pythonista/p/11178705.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/569146.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《吴恩达深度学习》第一课第四周任意层的神经网络实现及BUG处理

目录一、实现1、吴恩达提供的工具函数sigmoidsigmoid求导relurelu求导2、实现代码导包和配置初始化参数前向运算计算损失后向运算更新参数组装模型3、问题及思考一、实现 1、吴恩达提供的工具函数 这几个函数这里只是展示一下&#xff0c;这是吴恩达写好的工具类&#xff0c;…

球形坐标和Cartesian 坐标的转换 spherical coordinate

spherical coordinate 和cartesian坐标的转换&#xff0c; 个人认为在控制camera的时候最为有用&#xff0c;比如CS中的操作方式&#xff0c; 鼠标负责方向的改变&#xff0c;其恰恰就是球形坐标的改变。而camera的位置改变就是cartesian的改变&#xff0c;所以这两者的转换就必…

【HANA系列】SAP HANA Studio出现Fetching Children...问题

公众号&#xff1a;SAP Technical本文作者&#xff1a;matinal原文出处&#xff1a;http://www.cnblogs.com/SAPmatinal/ 原文链接&#xff1a;【ABAP系列】SAP HANA Studio出现"Fetching Children..."问题前言部分 大家可以关注我的公众号&#xff0c;公众号里的排版…

朴素Bayse新闻分类实践

目录1、信息增益&#xff08;互信息&#xff09;介绍&#xff08;1&#xff09;西瓜书中的信息增益[^1]&#xff08;2&#xff09;PRML中的互信息[^2]&#xff08;3&#xff09; 其实他们是一个东西2、朴素Bayse新闻分类[^3]&#xff08;1&#xff09;常量及辅助函数&#xff0…

【数据仓库】OLTP系统和OLAP系统区别

OLTP&#xff1a;联机事务处理系统(OnLine Transaction Processing) OLAP&#xff1a;联机分析处理系统(OnLine Analytical Processing) 参考文档&#xff1a; 操作数据库系统(OLTP)和联机分析处理系统(OLAP)的区别转载于:https://www.cnblogs.com/badboy200800/p/11189478.htm…

Good Numbers(HDU5447+唯一分解)

题目链接 传送门 题面 题意 首先定义对于\(k\)的好数\(u\)&#xff1a;如果\(u\leq k\)且\(u\)的所有质因子与\(k\)的质因子一样则称\(u\)对于\(k\)是一个好数。 现给你两个数\(k1,k2(1\leq k1,k2\leq 10^{24})\)&#xff0c;要你求\(k1,k2\)的好数个数&#xff0c;对于\(k1,k2…

从机器码到面向对象

1.从机器码到面向对象 本章节主要探讨是什么驱动着编程从机器码发展到了汇编语言&#xff0c;又从汇编语言发展到了面向过程编程&#xff0c;最后从面向过程编程发展到面向对象编程。通过这些探讨最终明确多年来的软件工程发展我们都解决了哪些棘手的问题。 1.1机器码 在真正…

spfa_队列

spfa:1.当给定的图存在负权边时&#xff0c;Dijkstra等算法便没有了用武之地&#xff0c;而Bellman-Ford算法的复杂度又过高&#xff0c;SPFA算法便派上用场了.2.我们约定有向加权图G不存在负权回路&#xff0c;即最短路径一定存在3.思路&#xff1a;用数组d记录每个结点的最短…

Tomcat配置解析

Tomcat文件配置 tomcat解压后目录 bin&#xff1a;可执行文件&#xff08;startup.bat shutdown.bat) conf&#xff1a;配置文件&#xff08;server.xml&#xff09; lib&#xff1a;tomcat依赖的jar文件 log&#xff1a;日志文件&#xff08;记录出错等信息&#xff09; temp&…

教你配置安全的ProFTPD服务器(中)

二、 基本加固ProFTPD服务器步骤 1.升级版本 注&#xff1a;如果当前版本已经是最新版本&#xff0c;可以跳过第一步。 升级陈旧的ProFTPD版本&#xff0c;因为早期的ProFTPD版本存在的安全漏洞。对于一个新配置的ProFTPD服务器来说使用最新稳定版本是最明智的选择&#xff0c;…

Java 将Word转为PDF、PNG、SVG、RTF、XPS、TXT、XML

同一文档在不同的编译或阅读环境中&#xff0c;需要使用特定的文档格式来打开&#xff0c;通常需要通过转换文档格式的方式来实现。下面将介绍在Java程序中如何来转换Word文档为其他几种常见文档格式&#xff0c;如PDF、图片png、svg、xps、rtf、txt、xml等。 使用工具&#xf…

CentOS7上GitLab的使用

生成SSH Keys 生成root账号的ssh key # ssh-keygen -t rsa -C "adminexample.com" 显示pub key的值 # cat ~/.ssh/id_rsa.pub 复制显示出来的 pub key 以root账号登陆gitlab&#xff0c;点击 "profile settings" 然后点击 "SSH Keys" 将复制的pu…

数据库:除运算

除运算 设关系R除以关系S的结果为关系T&#xff0c;则T包含所有在R但不在S中的属性及其值&#xff0c;则T的原则与S的元组的所有组合都在R中。用象集来定义除法&#xff1a;给定关系R&#xff08;X&#xff0c;Y&#xff09;和S&#xff08;Y&#xff0c;Z&#xff09;。其中X&…

[图解tensorflow源码] 入门准备工作附常用的矩阵计算工具[转]

[图解tensorflow源码] 入门准备工作附常用的矩阵计算工具[转] Link: https://www.cnblogs.com/yao62995/p/5773142.html tensorflow使用了自动化构建工具bazel、脚本语言调用c或cpp的包裹工具swig、使用EIGEN作为矩阵处理工具、Nvidia-cuBLAS GPU加速计算库、结构化数据存储格式…

现共收到 5 个分组,其目的地址分别为: (1) 128.96.40.10 (2) 128.96.41.12 (3) 128.96.41.151 (4) 192.4.123.17 (5) 192.4.

计算目的地址的下一跳&#xff1a; 设某路由器建立了如表 1 所示路由表。现共收到 5 个分组&#xff0c;其目的地址分别为&#xff1a;(1) 128.96.40.10(2) 128.96.41.12(3) 128.96.41.151(4) 192.4.123.17(5) 192.4.123.90试分别计算下一跳解答&#xff1a; 用目的IP地址和路由…

【转】Docker学习_本地/容器文件互传(5)

1、查找所有容器 #docker ps a 2、找出我们想要的容器名字并查找容器长ID #docker inspect -f {{.ID}} python 3、拷贝本地文件到容器 docker cp 本地路径 容器长ID:容器路径docker cp /Users/xubowen/Desktop/auto-post-advance.py 38ef22f922704b32cf2650407e16b146bf61c221…

数据流图典型例题

数据流图典型例题 1.假设一家工厂的采购部每天需要一张订货报表&#xff0c;报表按零件编号排序&#xff0c;表中列出所有需要再次订货的零件。对于每个需要再次订货的零件应该列出下列数据&#xff1a;零件编号、零件名称、订货数量、目前价格、主要供应商、次要供应商。零件…

白盒测试的逻辑覆盖辨析(语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖)

白盒测试逻辑覆盖&#xff08;语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖&#xff09; 逻辑覆盖测试&#xff1a; 语句覆盖&#xff1a;每条语句至少执行一次判定覆盖&#xff1a;每一判定的每个分支至少执行一次条件覆盖&#xff1a;每一判定中的每个条件&…

03 CSS听课笔记

CSS&#xff1a;页面美化和布局控制 1. 概念&#xff1a; Cascading Style Sheets 层叠样式表层叠&#xff1a;多个样式可以作用在同一个html的元素上&#xff0c;同时生效 2. 好处&#xff1a;(1)功能强大(2)将内容展示和样式控制分离   * 降低耦合度。解耦   * 让分工协作…

安装MySQL时出现“服务没有响应控制功能。请键入 NET HELPMSG 2186 以获得更多的帮助。”的问题解决

安装MySQL时出现“服务没有响应控制功能”的问题解决第一步&#xff1a;设置环境变量第二步&#xff1a;初始化my.ini第三步&#xff1a;添加文件第一步&#xff1a;设置环境变量 安装MySQL时&#xff0c;运行“net start mysql”时出现“服务没有响应控制功能。请键入 NET HE…