前言
最近在刷题/开发过程中遇到了有关指针的问题,特来记录,希望今后不要再受指针和引用的困扰。
C++ version
1.交换两个变量的值
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
2.交换一个数组中两个元素的值(刷题常用)
有一个这样的swap函数,考虑到与标准库的冲突,我起名为my_swap()
void my_swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
这个函数是用来交换数组中两个元素的值的。
int main()
{
int a[2] = {2, 250};
my_swap(a[0], a[1]);
cout << "a[0]:" << a[0] << " a[1]:" << a[1] << endl;
return 0;
}
a[0]:250 a[1]:2
为什么交换数组的时候,取法这么特殊?为什么int类型的变量可以赋值为int &?
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。
一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
想到这里,心中的疑惑就差不多烟消云散了。
int temp = a;,我们可以cout出来试一下。
他并没有打印一个地址,而是就打印的值。引用可以初始化为某个变量,并且通过改变引用的方式改变地址,进而改变值。
Go version
Go语言的交换变量就没有这么麻烦了。
a[i], a[j] = a[j], a[i]即可。Go的元组赋值法会让一切简单起来。
新的问题又出现了,观察到Go语言的项目中用了很多指针,并且传入参数也是传入指针,传入指针的意义何在?
我在查找问题答案的过程中,发现这样一篇专栏:Go只有值传递?
分析与举例
Example 1
假设现在有一个user实例对象,我们要在数据库中查找/创建这条记录。
db.Create(&user)或者db.Find(&user, 1)传入的都是这个实例对象的引用。
传引用就相当于传入他的地址。
如果传入的就是原本的值,函数调用时,实参通过拷贝将自身内容传递给形参,形参实际上是实参值的一个拷贝。此时,针对函数中形参的任何操作,仅仅是针对实参的副本,不影响原始值的内容。所以才有了传入地址的概念。
Example 2
type user struct {
Name string
Age int8
}
man := user{Name: "sb"}
man.Age = 20
fmt.Println(man.Age)
20
如果改为:
man := &user{Name: "sb"}
man.Age = 20
fmt.Println(man.Age)
20
都是一样的,一个实例对象能访问的成员,他的指针一样能访问。
但是如果是函数传参,可能就不会在函数内改变它的值了。此处不再附上代码。