指针地址与左右值
C++中,免不了要与指针和地址打交道,但是看着繁多的*
和&
有时又容易混乱。
*
与&
简单来说*
在声明时代表的是变量所处地址的指针,可以理解为幸运大转盘的箭头,指向幸运大转盘的一个位置,也就是变量所处的地址。而&
表示的就是取该变量的地址,也就是大转盘针头指着的地方。
1 | void main() { |
如上所示,&num
打印出来后就是该变量所处的地址信息,也许是40013ac7H,而第四行的int*
则是声明了一个指向num
地址的指针,这里容易混淆,为何赋值表达式左右是*
和&
,但意义却不一样?其中*
更像一个定位的标志,告诉你该指针现在指向什么地方,比如在连续空间(如数组)中,可以通过对指针进行加法操作:p++
来进行顺序访问数组元素,也就是让本指向数组中某个位置的箭头往后移动一位。
1 | void main() { |
其中如果在指针变量前加入*
则可以获得指针指向的存储空间的内容,这里就是1,而再在前方加上&
则可以获取到指针在内存中的地址,毕竟哪怕是一个箭头既然声明了,那么也需要相应的内存空间进行存储。
如果我们再次进行*
操作:
1 | void main() { |
其中*&p
中&p
是指针(也就是箭头)的地址,那么刚才说了,加上*
可以获得箭头所指的内容,那么实际上箭头所指的就是num
的地址,也就是&num
。如果再加上*
那么就能取到&num
地址所存放的内容,也就是1了。
左值与右值
左值很好解释:
1 | void main() { |
这些在内存中占用空间并拥有地址的值,都是左值,那么什么是右值?
1 | void main() { |
其中1 + 2
就是右值,它只是一个临时的表达式,并没有自己的地址,同时如果去取地址也只会得到报错。
那么右值有什么用呢?在传统的c++中,一行普通的代码可能如下:
1 | class A {} |
这时候我们会有什么样的操作呢?我们可能得到了b的复制(当然取决于如何定义operator=),但是这样呢?
1 | class A {} |
这时候b + b
明显的是一个右值,我们是否可以得到复制呢?参数列表中我们往往会声明一个A& a
的参数,但是刚才有说过,右值往往不拥有自己的地址,那么我们的代码就只能报错了吗?(假定已经实现了operator+
),不尽然:
1 | class A {} |
我们可以看到,参数列表中的变量类型为A&&
,这时候我们就可以简单的捕获到右值了。
右值引用的加入,使得我们可以更好的分辨出移动与复制,也填补了C++中的空白。