指针*与引用&

1.指针和引用的定义和性质区别:

(1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来

的变量实质上是同一个东西,只不过是原变量的一个别名而已。如:

int a=1;int *p=&a;

int a=1;int &b=a;

上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址。

而下面2句定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单

元。

(2)引用不可以为空,当被创建的时候,必须初始化,而指针可以是空值(NULL),可以在任何时候被初始化。

(3)可以有const指针,但是没有const引用;

(4)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)

(5)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;

(6)指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。

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

(8)指针和引用的自增(++)运算意义不一样;

(9)如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏;

示例

如下示例,要求在 func( p)中,m_value值和 参数 p 指代的实际内容值相同;
且之后 m_value值的改变,会影响 p 的实际内容;

仅一级指针实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;

int m_value = 1;

//一级指针参数
void func(int * p, int dest)
{
m_value = dest;
*p = m_value;
}

int main(int argc, char *argv[]) {
int n = 2;
int *pn = &n;
cout << *pn << endl; //初始值

func(pn, 77);
cout << *pn <<endl; //经过 func 函数后

m_value = 88;
cout << *pn <<endl; //改变 m_value 后
}
1234567891011121314151617181920212223

程序输入:

1
2
3
4
2
77
77
123

发现 后面改变了 m_value 值 ,并不影响 *pn。 这不合要求

二级指针实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using namespace std;

int m_value = 1;

//二级指针参数
void func(int ** p, int dest)
{
m_value = dest;
*p = &m_value; //*p 表示一级指针 ,指向 m_value 内容的地址
}

int main(int argc, char *argv[]) {
int n = 2;
int *pn = &n;
cout << *pn << endl; //初始值

func(&pn, 77); //pn 是指针变量, &pn 就是二级指针
cout << *pn <<endl; //经过 func 函数后

m_value = 88;
cout << *pn <<endl; //改变 m_value 后
}

123456789101112131415161718192021222324

输出:

1
2
3
4
2
77
88
123

满足要求。

指针引用实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using namespace std;

int m_value = 1;

//指针引用参数
void func(int *& p, int dest)
{
m_value = dest;
p = &m_value;
}

int main(int argc, char *argv[]) {
int n = 2;
int *pn = &n;
cout << *pn << endl; //初始值

func(pn, 77); //传递一级指针就以
cout << *pn <<endl; //经过 func 函数后

m_value = 88;
cout << *pn <<endl; //改变 m_value 后
}

123456789101112131415161718192021222324

输出:

1
2
3
4
2
77
88
123

满足要求。

In addtion

关于int *a; int &a; int & *a; int * &a; (int*) &a

上述的四条语句,前面两个很好理解,而后面两个,大部分C++初学者都会比较困惑,今天我也是查阅了一些资料以后才恍然大悟。下面具体来说明一下:

1
2
3
4
5
6
7
8
9
10
int i;

int *a = &i;//这里a是一个指针,它指向变量i

int &b = i;//这里b是一个引用,它是变量i的引用,引用是什么?它的本质是什么?下面会具体讲述

int * &c = a;//这里c是一个引用,它是指针a的引用

int & *d;//这里d是一个指针,它指向引用,但引用不是实体,所以这是错误的
123456789

(int*) &a为取a的地址,然后进行强制类型转换,转为int类型的指针。

int * &aint & *a

我在写这两句语句时,在int*(&)间空了一格,而后面的&(*)紧跟a。原因是:分析此类语句时,最简单的办法就是从右往左读,离变量名最近的符号对其类型有最直接的影响,即先看a前紧跟的是什么,它决定了a的类型。例如,对于int & *a,此处是*,表示其首先是个指针,指针的类型是一个int型引用。而int后的一个空格是为了防止int *a, b;//a是指针,而b不是

假设有一个 int 类型的变量 apa是指向它的指针,那么*&a&*pa分别是什么意思呢?

*&a可以理解为*(&a)&a表示取变量 a 的地址(等价于 pa),*(&a)表示取这个地址上的数据(等价于 *pa),绕来绕去,又回到了原点,*&a仍然等价于 a。

&*pa可以理解为&(*pa)*pa表示取得 pa 指向的数据(等价于 a),&(*pa)表示数据的地址(等价于 &a),所以&*pa等价于 pa

int **a;

它的功能和int *&a一样,两者生成的二进制代码一样。这再一次说明了引用就是指针。