1 指针和引用的区别

1.定义

(1)什么是指针?

指针:对于一个类型T,T*就是指向T的指针类型,也即一个T*类型的变量能够保存一个T对象的地址。

(2)什么是引用?

引用:引用是一个对象的别名,主要用于函数参数和返回值类型,符号X&表示X类型的引用。


2.区别

(1)引用不可以为空,但指针可以为空。

引用是对象的别名,引用为空——对象都不存在,怎么可能有别名!所以定义一个引用的时候,必须初始化。
声明指针是可以不指向任何对象,因此,使用指针之前必须做判空操作,而引用就不必。

因此如果你有一个变量是用于指向另一个对象,但是它可能为空,这时你应该使用指针;
如果变量总是指向一个对象,你的设计不允许变量为空,这时你应该使用引用。

(2)引用不可以改变指向;但是指针可以改变指向。

虽然引用不可以改变指向,但是可以改变初始化对象的内容。例如:就++操作而言,对引用的操作直接反应到所指向的对象,而不是改变指向;而对指针的操作,会使指针指向下一个对象,而不是改变所指对象的内容。

(3)引用、指针大小不同。

引用的大小是所指向的变量的大小,因为引用只是一个别名而已;指针是指针本身的大小,4个字节。

(4)引用比指针更安全。

由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,因此引用很安全。
对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL,所以不安全。
const 指针虽然不能改变指向,但仍然存在空指针,并且有可能产生野指针(即多个指针指向一块内存,free掉一个指针之后,别的指针就成了野指针)。


总结:指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名,引用不改变指向。


(5)const对指针和引用的限定有差别。

常量指针VS常量引用
a.常量指针:指向常量的指针,在指针定义语句的类型前加const,表示指向的对象是常量。

定义指向常量的指针只限制指针的间接访问操作,而不能规定指针指向的值本身的操作规定性。
常量指针定义”const int* pointer=&a”告诉编译器,pointer是常量,不能将pointer作为左值进行操作,eg: *pointer=1;

b.常量引用:指向常量的引用,在引用定义语句的类型前加const,表示指向的对象是常量。

也跟指针一样不能利用引用对指向的变量进行重新赋值操作。eg: const int &pointer=i;pointer=1;

指针常量VS引用常量
a.指针常量:在指针定义语句的指针名前加const,表示指针本身是常量。在定义指针常量时必须初始化!而这是引用天生具来的属性,不用再引用指针定义语句的引用名前加const。

指针常量定义”int* const pointer=&b”告诉编译器,pointer是常量,不能作为左值进行操作,但是允许修改间接访问值,即*pointer可以修改。

b.引用常量: 引用变量就是引用常量.

常量指针常量VS常量引用常量
a.常量指针常量:指向常量的指针常量,可以定义一个指向常量的指针常量,它必须在定义时初始化。常量指针常量定义”const int* const pointer=&c”告诉编译器,pointer和*pointer都是常量,他们都不能作为左值进行操作。

b.不存在所谓的”常量引用常量”,因为跟上面讲的一样引用变量就是引用常量C++不区分变量的const引用和const变量的引用

程序决不能给引用本身重新赋值,使他指向另一个变量,因此引用总是const的。如果对引用应用关键字const,起作用就是使其目标称为const变量。即没有:Const double const& a=1;只有const double& a=1;


总结:有一个规则可以很好的区分const是修饰指针,还是修饰指针指向的数据——画一条垂直穿过指针声明的星号(*),如果const出现在线的左边,指针指向的数据为常量;如果const出现在右边,指针本身为常量。而引用本身与天俱来就是常量,即不可以改变指向。


3.左值引用 vs 右值引用

在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值(将亡值或纯右值)。

引用:就是取别名 ,引用不可以重定义。

举个例子,int a = b+c, a 就是左值,其有变量名为a,通过&a可以获取该变量的地址;表达式b+c、函数int func()的返回值是右值,在其被赋值给某一变量前,我们不能通过变量名找到它,&(b+c)这样的操作则不会通过编译。

(1)左值一定在内存中,右值有可能在内存中也有可能在寄存器中

int a=5;
int b=a;//此时a在内存中

int a=5;
int b=a+1;//此时a+1在寄存器中
int *p=&a;//此时&a在寄存器中

注意:在内存中的变量才是可以取地址的,而在寄存器中的变量是不可以取地址的。对于一个不能取地址的表达式或者值是无法直接引用的。

(2)左值引用就是对一个左值进行引用的类型。右值引用就是对一个右值进行引用的类型。

右值引用和左值引用都是属于引用类型。左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。

无论是声明一个左值引用还是右值引用,都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。

a.左值引用

int i = 42;
int &r = i;    //正确,左值引用
int &r1 = i * 42;   //错误, i*42是一个右值
const int &r2 = i * 42; //正确,可以将一个const的引用绑定到一个右值上

b.右值引用

int  &&rr = i;  //错误,i是一个变量,变量都是左值
int &&rr1 = i *42;  //正确,i*42是一个右值
int &&r2 = std::move(a);  //正确,使用std::move()将左值强制转换为右值

(3)为什么要右值引用?

右值引用在你需要使用寄存器中的值的时候可以进行右值引用。寄存器的刷新速度很快,没有右值引用的话就需要将寄存器中的值拷贝到内存中,在进行使用,这是很浪费时间的。

int getdata(int &&num)
{
cout << num;
num += 10;
return num;
}


void main()
{
int a = 5;
cout << getdata(a + 1) << endl;
}

如上int getdata(int &&num)就是对右值进行引用。

getdata(a + 1) 中a+1是右值在寄存器中,我们是不可以直接对他进行操作的,如果要操作得将其拷贝到内存中,如果是一个非常大的数据这种拷贝就会很占用内存,如果直接用右值引用就可以直接对其进行操作。从而节约内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值