前言
现在面试算法岗的工作,对于刚刚毕业的同学来说,基本都会问数据结构与算法的问题,还有python、C、C++这几种语言最好都要会,因为面试官可能会问你 “在python和C/C++中,XX有什么区别?” 这篇文章笔者以自己的一些面试经验,来回顾复习编程语言的基础知识点,范围涉及python、C/C++,欢迎各位批评指正。
之前有一次面试,面试官问我 “你说一下C和Python中指针有什么区别呢?”直接给我干懵了,C的指针我知道,python中有指针吗?
答案是:有的
1 C/C++中的指针
1.1 概念
在C和C++中,指针是一种特殊的变量类型,它存储了一个内存地址。这个内存地址指向计算机内存中的某个位置,而这个位置可能存储了特定类型的数据。
1.2 作用
指针的主要作用是允许我们直接访问和操作内存中的数据,而不需要通过变量名。通过使用指针,我们可以传递内存地址,使得多个变量可以引用和修改同一个数据。
1.3 指针声明与使用
在C中,指针的声明使用"*"符号。例如,下面是一个指向整数的指针的声明和初始化的示例:
int *ptr; //声明一个指向整数的指针
int num = 10;
ptr = # //将ptr指向num的地址
上面的代码中,ptr是一个指向整数的指针,通过"&“运算符,我们可以获取num变量的地址,并将其赋值给ptr。现在ptr指向num的地址,我们可以通过解引用操作符”*"来访问和修改num的值。例如:
*ptr = 20; //通过指针修改num的值
printf("%d", num); //输出为20
在C++中,指针的使用方式与C类似,但是C++还引入了引用类型。引用类型允许我们通过使用"&"符号创建一个别名,而不是直接通过指针来访问变量。这种方式更加方便和安全。
下面是一个在C++中使用指针和引用的示例:
int num = 10;
int *ptr = # //使用指针
int &ref = num; //使用引用
*ptr = 20; //通过指针修改num的值
ref = 30; //通过引用修改num的值
cout << num << endl; //输出为30
2 python中的指针
2.1 概念
python中没有显式的指针类型,而是使用对象引用来实现类似指针的功能,所以python中的指针是加了引号的“指针”。
在python中,变量实际上就是对象的引用。当我们创建一个变量并将其赋值给一个对象时,该变量实际上引用了该对象的内存地址,而不需要像C一样去声明。
2.2 作用
python的这种引用,允许我们通过变量来访问和操作对象。
在python中,变量之间的赋值实际上是将一个对象的引用复制给另一个变量。这意味着多个变量可以引用同一个对象。
2.3 “指针”的使用
(1)python中有使用变量的地方就有“指针”,如:
num = 10
num = 20 # 修改num引用的对象,将其指向另一个整数对象
在这段代码中,num 是一个变量,它引用了一个整数对象 10 的内存地址。我们可以通过变量名 num 来访问这个对象,并且可以对其进行操作。
a = [1, 2, 3]
b = a # 将b指向与a相同的列表对象
b.append(4) # 修改b引用的列表对象
print(a) # 输出为 [1, 2, 3, 4]
在上面的代码中,a 和 b 都引用了相同的列表对象,因此对其中一个变量所引用的对象进行的修改也会影响另一个变量。
(2)需要注意的是,Python中的引用是动态的,这意味着变量可以引用不同类型的对象。例如:
x = 10
x = 'hello'
x 首先引用了一个整数对象 10 的内存地址,然后又引用了一个字符串对象 ‘hello’ 的内存地址。这种灵活性是Python动态类型的一个特点。
2.3.1 浅拷贝
浅拷贝是创建一个新的对象,该对象的内容是原始对象的引用。换句话说,浅拷贝创建了一个新的对象,但是这个新对象仍然与原始对象共享一部分数据。如果原始对象包含引用类型的成员,浅拷贝将复制这些引用,而不是创建新的独立对象。比如:
import copy
list1 = [1, 2, 3]
list2 = list1.copy() # 进行浅拷贝
list2[0] = 5
print(list1) # 输出为 [1, 2, 3]
print(list2) # 输出为 [5, 2, 3]
可以用图示来理解:
其实就是用个新变量复制了一份引用,都引用同样的对象。可以让新变量去引用另一个对象,就起到了改变新变量内容而不改变旧变量内容的作用。
但是如果引用对象本身被修改,则会影响另一个。如:
import copy
list1 = [1, 2, [3, 4]]
list2 = copy.copy(list1) # 进行浅拷贝
list2[0] = 5
list2[2][0] = 6
print(list1) # 输出为 [1, 2, [6, 4]]
print(list2) # 输出为 [5, 2, [6, 4]]
list2 是通过浅拷贝 list1 创建的新列表。当我们修改 list2 的元素时,list1 不受影响。但是,当我们修改 list2 中的子列表 [3, 4] 的元素时,list1 也会受到影响,因为它们共享相同的子列表。
2.3.2 深拷贝
相比之下,深拷贝是创建一个全新的对象,该对象的内容与原始对象完全独立,包括所有引用类型的成员。深拷贝会递归复制原始对象及其所有嵌套对象,确保每个对象都是独立的。这样,对于深拷贝对象和原始对象之间的更改不会相互影响。换句话就是所有东西都复制一份,互相之间不共用。
深拷贝用deepcopy()函数来实现,比如:
import copy
list1 = [1, 2, [3, 4]]
list2 = copy.deepcopy(list1) # 进行深拷贝
list2[0] = 5
list2[2][0] = 6
print(list1) # 输出为 [1, 2, [3, 4]]
print(list2) # 输出为 [5, 2, [6, 4]]
总结
本文简单总结了C/C++和python中指针的概念以及使用,对于python中我们只介绍了列表的“指针”,还有元组没有讲到,下次再说,拜~