彻底讲明白C++中指针和引用的区别到底是啥!

学过C的都知道指针,刚开始学习指针的时候,都会觉得指针很难,学完了指针才发现指针就是保存的地址。指针十分不安全,使用的不恰当,就会使程序出错!C++里面提出了“引用”代替指针,提高程序的安全性。下面来讲讲什么是引用。

一、引用的定义

引用是给另外一个变量起别名,绑定一个变量,所以引用不会分配内存空间。对引用的所有操作,事实上都是作用在该引用所绑定的对象上。

引用的声明方法:类型标识符 &引用名=目标变量名;(如int &ptr = num;)

int main(int argc, char *argv[])
{
    int a =10;
    int *num= &a;
//int *num =a;是错误的
    int &b=a;
    printf("%p,%p,%p,%p\n",&b,&a,num,&num);
    printf("%d,%d,%d\n",b,a,*num);
    return 0;
}

 

从运行结果来看,num这个指针的值就是a的地址,而b的地址和a的地址相同,说明b和a是同一个内存单元格,只是有2个名字而已,就相当于对内存区域0028FF18这个单元格起了2个名字,叫a和b。你用a和b都可以访问0028FF18这个单元格。a和b就是一个东西。

二、引用与指针的区别

1、指针是一个实体,需要分配内存空间(你创建一个指针变量int *p,那么这个p必须在内存中占有一个单元格(其实是4个字节),它所占的单元格里面可以填一个地址,来表示它指向哪里。)。引用只是变量的别名,不需要分配内存空间(引用是对已经存在的一个单元格来说的,单元格已经存在了,引用就是对单元格再起一个名字,这个引用呢,不再在内存中存储了,参见上面的例子)。

2、引用在定义的时候必须进行初始化,并且不能够改变(引用是针对已经存在的某个单元格进行二次命名,所以单元格必须先存在)。指针在定义的时候不一定要初始化,并且指向的空间可变。(注:不能有引用的值不能为NULL)

3、有多级指针,但是没有多级引用,只能有一级引用。

4、指针和引用的自增运算结果不一样。(指针是指向下一个空间,引用时引用的变量值加1)

5、sizeof 引用得到的是所指向的变量(对象)的大小,而sizeof 指针得到的是指针本身的大小。

6、引用访问一个变量是直接访问,而指针访问一个变量是间接访问。

扫描二维码关注公众号,回复: 5647826 查看本文章

使用引用有何优点?

  在传参的时候,使用指针传参,编译器需要给指针另行分配存储单元,存储一个该指针的副本,在函数中对这个副本进行操作;而使用引用传参,编译器就不需要分配存储空间和保存副本了,函数将直接对实参进行操作。所以使用引用使得程序的运行速度更快,执行效率更高。

三、引用的示例

1. 交换数字

void swap(int &a, int &b)
{
	int tmp;
	tmp=a;
	a=b;
	b= tmp;
}

int main()
{
	int a = 3;
	int b = 5;
	cout << "交换前, a= " << a << ", b= " << b << endl;
	swap(a, b);
	cout << "交换后, a= " << a << ", b= " << b << endl;
    return 0;
}

 

通过上面的例子我们发现,使用引用作为参数进行函数定义的好处:只需要在函数定义(void swap(&a,&b))的时候,将参数写成参数的引用形式。在实参的定义时只管写实参就行(int a,b;),在函数调用时,传进去的也是实参(swap(a,b)),根本不需要用指针或者引用符。 

专业点说,就是引用在函数传参的时候,只需要传变量名过去,函数形参用引用接即可。而指针在传参的时候,必须传变量的地址过去,否则不能改变变量的值。
引用没有分配内存空间,所以访问函数形参就是访问引用的变量,是直接访问。而指针分配了内存空间用来保存变量的地址,需要通过保存的地址找到指向的变量,是间接访问。

2. 作为函数返回类型

#include <iostream>
using namespace std;
 
int& func(int &tmp)
{
	return tmp;
}
 
int main()
{
	int num = 1;
 
	cout << "num = " << num << endl;
 
	func(num) = 3;
 
	cout << "change num = " << num << endl;
 
    return 0;
}

结果:

num = 1

change num = 3

3. 引用、指针、指针引用等

int val3 = 100;
    int &value3 = val3;   // 定义一个【引用】 ,和变量val3绑定到一起
    int *ptr3 = &val3;   // 定义一个【指针】,其值为val3的地址,也就是ptr3指向了val3所在的内存单元,该单元的内容是100

    int *&refp3 = ptr3;    //将一个【指针引用】和一个指针绑定起来,那么refp就是一个【指针引用 】 ,它和ptr3是一个东西

    cout << "val3 的值:                        " << val3 << endl;
    cout << "value3 的值:                      " << value3 << endl;

    cout << "val3所在的内存地址         &val3 : " << &val3 << endl;  // 【取地址】
    cout << "value3所在的内存地址     &value3 : " << &value3 << endl;  // 【取引用】
    cout << "指针ptr3所指向的内存地址   ptr3  : " << ptr3 << endl;       //
    cout << "对*ptr3指向的内容的取地址  &*ptr3: " << &*ptr3 << endl;  // 【注意:ptr3 = &val3 = &*ptr3 】

    cout << "获取指针ptr3指向地址的内容 *ptr3 : " << *ptr3 << endl;   // 【解引用】
    cout << "获取指针ptr3的地址         &ptr3 : " << &ptr3 << endl;
    cout << "\n" ;

    cout << "获取指针引用refp3 的地址   refp3 : "<< refp3 << endl;   // 【指针引用refp】同样指向
    cout << "\n" ;

    cout << " (&)取地址 和 (*)解引用* 互为反向操作因此,可以推理出,&*&*ptr依旧还是val的地址:\n" << &*&*ptr3 << endl;

 

参考:

https://blog.csdn.net/zhengqijun_/article/details/54980769 

https://blog.csdn.net/cjolj/article/details/55503742

猜你喜欢

转载自blog.csdn.net/jinking01/article/details/88691535