指针和引用与及指针常量和常量指针
指针和引用的区别
1.存在空指针,但是不存在空引用。
2.指针可以不初始化,而引用必须初始化,并且,引用的目标一旦确定,后面不能再更改,指针可以更改其指向的目标。
3.指针是一个实体,而引用仅是个别名。
4.引用是类型安全的,而指针不是 (引用比指针多了类型检查)
5.指针和引用的自增(++)运算意义不一样,对引用的操作直接反应到所指向的对象,而不是改变指向;而对指针的操作,会使指针指向下一个对象,而不是改变所指对象的内容。
6.存在指针数组 ,不存在引用数组,不允许使用引用数组,因为引用没有内存的分配。
7.引用传递过程中,被调函数的形式参数作为局部变量在栈中开辟内存空间,但是这时存放的是由主调函数放进来的实参变量的地址
;
同样,指针传递参数时,指针中存放的也是实参的地址
,但是在被调函数内部指针存放的内容可以被改变
,即可能改变指向的实参
,所以并不安全,而引用则不同,它引用的对象的地址一旦赋予,则不能改变。
测试
跑一跑,然后对比理解看看。
#include <iostream>
using namespace std;
int main()
{
/*
指针和引用使用细节
*/
cout<<"指针和引用使用细节: "<<endl;
int a =3,c=3,d=3;
int *p = &a;
int &b = a;
cout<<p<<" "<<*p<<" "<<&p<<endl;
cout<<--(*p)<<endl; //通过指针改变指向的值
cout<<b<<" "<<&b<<" "<<a<<endl;
cout<<"********************************"<<endl;
/*
常量指针和常量引用
*/
//这种一般是用于指向常量,这里例举的是普通变量,一般不推荐这么用,太容易混淆。
const int *p2 = &c; //*p2是常量
const int &b2 = c;
cout<<"常量指针和常量引用: "<<endl;
cout<<*p2<<endl;
//cout<<--(*p2)<<endl; //常量指针不可改
c--; //指向的变量可改,如果c本身为常量便不可改
cout<<*p2<<endl;
//cout<<--b2<<endl; //常量引用不可改
c--;
cout<<b2<<endl;
p2 = &a; //p2不是常量,可改变指向
cout<<*p2<<" "<<p2<<endl;
cout<<"********************************"<<endl;
/*
指针常量和引用常量
*/
cout<<"指针常量和引用常量: "<<endl;
int *const p3 = &d; //p3是常量
int &b3 = d; //引用本身就是常量,不用再使用const修饰
//p3 = &a; //出错,p3为常量,不可修改指向
cout<<*p3<<endl;
cout<<--(*p3)<<endl; //可修改
d--; //这个自然是可改的
cout<<*p3<<" "<<d<<endl;
cout<<"********************************"<<endl;
/*
常量指针常量
*/
cout<<"常量指针常量: "<<endl;
const int x=3;
const int *p4 = &x; //如果是常量,指针的定义只能这样`const int *p = &x;`且必然不可改
cout<<*p4<<" "<<x<<endl;
return 0;
}
对于指针常量和常量指针的记忆
有一个规则可以很好的区分const是修饰指针,还是修饰指针指向的数据——画一条垂直穿过指针声明的星号(*),如果const出现在线的左边,指针指向的数据为常量;如果const出现在右边,指针本身为常量。而引用本身与天俱来就是常量,即不可以改变指向。
也可以这样记:
- 指针常量 -> 指针为常量,不可改变指向,但可修改指向的值。
- 常量指针 -> 常量的指针,可改变指向,不可修改指向的值。
参考
有疑问时多看看(推荐):C++中引用,指针,指针的引用,指针的指针
感谢阅读,如有问题,请批评指正,谢谢。