引用和指针的区别和联系(面试之中非常爱考的知识点)
指针和引用性质的区别
1)指针是一个变量,只不过这个变量存放的是一个地址,指向内存的一个存储单元。
引用:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。
int a=1;int *p=&a;
int a=1;int &b=a;
2)可以有const 指针,没有const引用;
3)指针可以有多级,但是引用只能是一级;(int **p是合法的,但是int&& a 是不合法的;)
4)指针的值可以为空,但是引用的值不能为NULL;并且引用在使用的时候必须进行初始化;
5)指针的值在初始化之后是可以进行改变的,但是引用的值在初始化之后就不能进行改变了,而且是从一而终的。
6)sizeof引用指向的是指向变量(对象的大小),而sizeof指针指向的是指针本身的大小;
7)指针和引用的自增(++)意义不一样;
8)相对而言指针比引用更安全(指针会出现野指针的问题)
指针和引用的相同点
指针和引用都是地址上面的概念
指针指向是一段内存空间,它的内容是所指内存的地址
引用是一段内存的别名
引用定义格式
类型 &引用变量名=已定义过的变量名
引用的特点
- 1、一个变量可以取多个别名
- 2、引用必须初始化
- 3、引用只能在初始化的时候引用一次,不能改变再去引用其他的变量
const修饰的指针
const int* p;//const修饰*p,指向的内容不可以改变
int const* p;//const修饰的是*p,指向的内容不能够改变
int* const p;//指向内容可以被改变,指针本身可以改变
const int* const p;//指向的内容和指针本身都不改变
int a = 1;
int* p1 = &a;
const int* p2 = p1;
//权限被缩小了,所以可以正确
const int* p1 = &a;
int* p2 = p1;
//不可以,因为const修饰的是*p1,所以*p1是不可以改变的
//而p2是int*的,所以是可读可写的,p1赋给p2
//权限被放大。const* 不可以转换成为int*;
int const *p1 = &a;
int* p2 = p1;
//p1是可读的,赋值给p2变成了只读只写的,权限被放大,所以不通过
int* const p3 = &a;
int* p4 = p3;
//等价于const int a;
// int b=a;
//b的改变不会影响到a,同样的p4的改变不会影响*p3的值。
int* p1 = &a;
int* const p2 = p1;
//正确,因为const修饰p2,p2不能改变,将p1赋给p2是可以的
int* p3 = &a;
int const *p4 = p3;
//正确,p3是可读可写的当我们赋给p4是可读的,权限被缩小也是可以的
const修饰引用
const int a = 10;
int& b = a;
//a是常量,不能给常量赋值
const int a = 10;
const int&b = a;
//正确,常量具有常性,只有常引用可以引用常量
double a = 1.1;
int& b = a;
//a是double类型的,b是int类型的,a赋值给b实际上要生成一个
//临时变量,b实际上引用的是这个带有常属性的临时变量,所以
//不能赋值。
const int& c = a;//正确,常引用可以引用常量
权限可以被缩小,但是不能被放大,这里针对的是引用
引用作为参数
- 值传递
- 引用传递
- 指针传递
/如果形参是非引用的传值方式,则生成局部临时变量接收实参的值
//值传递,不能实现交换,因为传参时,对于参数a和参数b只是
//拷贝的一个临时副本,交换的是副本值,因为其是临时变量函数
//退出,变量销毁,并不会影响外部a和b的值;
void swap(int a, int b)//值传递,不能实现交换,
{
int tmp = a;
a = b;
b = tmp;
}
//如果形参是引用类型,则形参只是实参的别名
//使用引用的话不会做临时的拷贝,&的使用说明的
//此处只是原参数的另一个名字而已,所以修改时
//直接在原参数的基础上修改变量值
void swap(int& a, int& b)//引用传递
{
int tmp = a;
a = b;
b = tmp;
}
//传入的是地址,因为地址是唯一的,所以指针通过地址的访问
//进而可修改里面的内容
void swap(int* pa, int* pb)//指针传递
{
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
引用的返回值
1)传引用作返回值
2)传值作返回值
如果返回对象出了当前函数作用域还在,使用引用(效率高);
如果返回对象出了当前函数作用域不存在,就使用传值返回;
牛刀小试—–看下面
#include <iostream>
using namespace std;
void swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
void test()
{
int *p = 0;
int& a = *p;//a是一个指针*p的别名,而b是一个int型的,
//形参int& x其实得到的是一个指针类型的值,所以看似程序没有任何问题
//其实程序隐藏着巨大的危机。
int b = 2;
swap(a, b);
}
int main()
{
test();
system("pause");
return 0;
}
运行结果,出现了致命性的错误!!!