主要说一下C++指针和引用在使用过程中需要注意的一些地方。
一、指针
1.指针其实就是内存地址,数据(无论是int/long/char等各种类型)存储在内存中,必然有找到存储数据的办法,这个办法就是找到存储这部分内存的地址就可以了。找到了地址就找到就找到了放到地址中的内容,这就是指针的功能。在C/C++中指针就是内存地址,取出地址中存放的内容的符号也是比较形象的,-> 是不是很像一个箭头!通过这个符号就可以取出当前地址下的内容。
当然了,还可以使用解引用,使用*来取出地址中的内容;
2.作为指针经常被作为参数传递,比如:
#include <stdio.h>
//求arg1+arg2=sum把结果保存到sum中
void testAdd(int* arg1, int*arg2, int*sum);
int main() {
int arg1 = 12;
int arg2 = 5;
int sum = 0;
printf("调用之前地址:arg1地址:%0xd arg2地址:%0xd sum地址:%0xd\n", &arg1, &arg2, &sum);
testAdd(&arg1, &arg2, &sum);
printf("%d+%d=%d\n", arg1, arg2, sum);
return 0;
}
void testAdd(int* arg1, int*arg2, int*sum) {
*sum = *arg1 + *arg2;
printf("调用之后地址:arg1地址:%0xd arg2地址:%0xd sum地址:%0xd\n", arg1, arg2, sum);
}
输出结果:12+5=17
通过内存地址可以看到:
参数传递的确是传递的同一个地址中的内容。
以上计算是通过指针完成的。但是如果不适应指正呢?直接传值会怎样?我们重载一下函数:
void testAdd(int arg1, int arg2, int sum);
void testAdd(int arg1, int arg2, int sum) {
sum = arg1 + arg2;
printf("调用之后地址:arg1地址:%0xd arg2地址:%0xd sum地址:%0xd\n", &arg1, &arg2, &sum);
}
运行一下,查看结果:
发现各个参数的地址都不一样了,而且计算的结果也不对。这是因为在调用函数testAdd时,系统会在函数内部自动的分配同类型的临时变量,并且把传递的参数复制给生成的临时变量。之后再函数中对这些变量的使用其实是对生成的临时变量的使用,与原来的变量不是同一个变量了。他们是位于内存中不同地址的不同变量。所以在函数中的变量和调用函数之外的变量虽然类型名字一样,但是不是同一块内存。因此结果也是不正确的。
二、引用
1.如果我们把上面的函数在修改一下,传递的参数改为引用。
void testAdd(int&arg1, int&arg2, int&sum);
void testAdd(int&arg1, int&arg2, int&sum) {
sum = arg1 + arg2;
printf("调用之后地址:arg1地址:%0xd arg2地址:%0xd sum地址:%0xd\n", &arg1, &arg2, &sum);
}
然后运行一下,查看结果:
`
返现运行也是正确的。
引用其实作用和指针的作用是一样的,指针是地址,引用是别名。举个例子:我给张三起了另外一个名字叫张三三,当我叫张三或者张三三时,他们都是同一个人。引用就是这样。
参数传递的是引用,在函数内部使用这个别名变量任然是函数外面定义的别名。在函数内部对这个变量的操作,也就是对在函数外部变量的操作。它们是内存中的同一块内存,只不过是不同的名称而已。
但是如果返回的是引用呢?网上很多人都说不要返回局部变量的引用,返回又如何?举个例子:
int& testAdd(int arg1, int arg2);
int& testAdd(int arg1, int arg2) {
int sum = arg1 + arg2;
printf("调用之后地址:arg1地址:%0xd arg2地址:%0xd sum地址:%0xd\n", &arg1, &arg2, &sum);
return sum;
}
编写完成之后,会在第一次编译的时候,出现如下警告:
warning C4172: 返回局部变量或临时变量的地址
忽略警告直接运行:
调用前和调用后的内存地址是不一样的,但是结果确实正确的。这是因为放返回的变量是临时变量的时候,临时变量会在函数调用完成后就释放掉内存了。返回时会重新分配一块同类型的内存一保存返回值。所以内存地址会不一样。
2.返回值是引用,对引用的操作
直接上代码,看下面的例子:
#include <stdio.h>
int gSum = 0;
int& testAdd(int arg1, int arg2);
int main() {
int arg1 = 12;
int arg2 = 5;
printf("1.gSum地址:%0xd\n", &gSum);
int sum = testAdd(arg1, arg2);
sum++;
printf("sum地址:%0xd\n", &sum);
printf("2.gSum地址:%0xd\n", &gSum);
printf("gSum=%d\n", gSum);
return 0;
}
int& testAdd(int arg1, int arg2) {
gSum = arg1 + arg2;
return gSum;
}
gSum的值是17还是18?
看打印出来的结果:
gSum=17并且sum的地址和gSum的地址也是不一样的,为什么呢?这是因为testAdd函数虽然返回的是引用,但是接收返回值的并不是引用,认识具体的一个变量,相当于又重新分配了一块内存,然后给分配这块内存重新赋值。这块内存和gSum是不同的内存位置。
那么如果我想返回也是gSum呢,那么就要接收返回值的地方必须也是定义为引用。
int&sum = testAdd(arg1, arg2);//要定义成引用
重新运行一下:
sum和gSum的结果地址一样的,对sum的操作也就是对gSum的操作。sum就是gSum的别名引用。
以上!