指针
指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元。
引用
引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。(教科书标准)
指针与引用的区别
- 引用不可以为空,当被创建的时候,必须初始化,而指针可以是空值,可以在任何时候被初始化
- 有const指针,但是没有const引用
- 指针的值可以为空,但是引用的值不能为空,并且引用在定义的时候必须初始化
- 指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变
-
sizeof 引用
得到的是所指向的变量(对象)的大小,而sizeof pointer
”得到的是指针本身的大小,在64位机器下为8字节 - 指针可以有多级,但是引用只能是一级
- 如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏
- 指针和引用的自增(++)运算意义不一样
函数传参
指针传参数
演示代码如下,编译g++ main.c -o main -std=c++11
:
#include <iostream>
#include "stdio.h"
using namespace std;
void swap(int *a, int *b) {
int *tmp = a;
a = b;
b = tmp;
}
void testp(int *p) {
int c = 5;
p = &c;
cout << p << " " << *p << endl;
}
int main(int argc, char** argv) {
int a = 1, b = 2;
swap(&a,&b);
cout << a << " " << b << endl;
int *p = nullptr;
testp(p);
if (p == nullptr)
cout << "p is nullptr" << endl;
else
cout << p << " " << *p << endl;
return 0;
}
编译运行之后的结果:
image.png
可以观察到的结果:
-
swap
函数没有交换a,b
的值 - 在
testp
函数中指针p是地址,*p
取到了变量c
的值 -
testp
函数没有返回后没有改变传入的指针参数p
引用传参数
#include <iostream>
#include "stdio.h"
using namespace std;
void testp(int &p) {
cout << &p << " " << p << endl;
p = 5;
cout << &p << " " << p << endl;
}
int main(int argc, char** argv) {
int p = 1;
cout << &p << " " << p << endl;
testp(p);
return 0;
}
可以看到结果:
- 变量P三次地址都没有改变
- 变量P的值在函数
testp
中最后一次改变了
运行如下:
image.png
引用实质
我们知道在C
语言中无法使用引用传参数,引用传参数是C++
的语法。那么C语言中如何实现类似的功能呢?
#include "stdio.h"
void swap(int *const a, int *const b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int main(int argc, char** argv) {
int x=10,y=20;
swap(&x,&y);
printf("%d %d\n", x, y);
return 0;
}
如上代码就是C语言中的实现,同样也能实现x,y
的值交换,只不过函数传的参数是int *const
类型。
实际上,在引用中int &b=a
这一句代码可被编译器看做int * const b=&a
,加上const的作用是表明指针b的自身的值(a的地址)不能改变,而指向的值(a的值)可以改变。也就是说引用相当于指针,引用与指针在编译时的方法一样,指向的都是变量的内存地址。但是也有一些不同点如下:
- 在定义方式中引用储存的是值,而指针是一个变量的拷贝,存储的是地址
- 引用只能对已经存在的变量或对象实现引用,而指针则不需要,可以定义为空
- 在函数的传参中,如果传递的是一个引用,意味着这个变量或对象已经存在了;如果传递的是一个指针,则不能判断这个指针是不是有效的,是不是空的,因此在函数体 中大多数都得进行指针是否为空的判断。但是虽然引用较为安全,但是利用指针来传参效率较快
- 引用是直接访问变量,不用分配自己的内存空间,而指针是间接访问,需要定义,需要有自己的内存空间
所以实际开发中,使用哪种方式应该由开发者自己来定,按照开发的需求来定。
网友评论