C++-----------------指针和引用

引用和指针的区别和联系(面试之中非常爱考的知识点)

指针和引用性质的区别
1)指针是一个变量,只不过这个变量存放的是一个地址,指向内存的一个存储单元。
引用:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。

int a=1int *p=&a;
int a=1int &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;
}

运行结果,出现了致命性的错误!!!
这里写图片描述

猜你喜欢

转载自blog.csdn.net/daboluo521/article/details/80920909
今日推荐