首先,我在网上搜索了下C++指针和引用的区别,得到的结果大致如下:
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)可以有const指针,但是没有const引用; (3)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的) (4)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化; (5)指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。 (6)"sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小; (7)指针和引用的自增(++)运算意义不一样;
首先我测试了第一条,但是发现并不是这样子,求高手指教。代码如下:
class A{
char name[];
int age;
};
void init()
{
A a;
A &aref1 = a;
A *aPointer = &a;
}
对应的汇编代码如下:
_Z4initv:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $16, %esp
leal -12(%ebp), %eax
movl %eax, -8(%ebp)
leal -12(%ebp), %eax
movl %eax, -4(%ebp)
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
看上面的汇编代码我们会发现指针和引用的操作都是一样的,且引用也占据着栈上的内存[-8(%ebp)]。
下面来看看引用和指针作为函数参数的表现是怎样的?
先来看看引用的情况,代码如下:
class A{
public:
char name[32];
int age;
};
void init(int off, A& a)
{
a.age = 25 + off;
}
对应的汇编代码如下:
_Z4initiR1A:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
leal 25(%eax), %edx
movl 12(%ebp), %eax
movl %edx, 32(%eax)
popl %ebp
.cfi_def_cfa 4, 4
.cfi_restore 5
ret
.cfi_endproc
从语句
movl 12(%ebp), %eax
movl %edx, 32(%eax)
我们看出【12(%ebp)】这里存放着传入A的实例的地址。
再来看看指针的情况,代码如下:
class A{
public:
char name[32];
int age;
};
void init(int off, A* a)
{
a->age = 25 + off;
}
对应的汇编如下:
_Z4initiP1A:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
leal 25(%eax), %edx
movl 12(%ebp), %eax
movl %edx, 32(%eax)
popl %ebp
.cfi_def_cfa 4, 4
.cfi_restore 5
ret
.cfi_endproc
我们可以看出和上面引用的情况是一样的。
3. 对引用取地址
代码如下:
class A{
char name[];
int age;
};
void init()
{
A a;
A &aref1 = a;
A *aPointer = &a;
int ptr = (int)&aref1;
}
汇编如下:
_Z4initv:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $16, %esp
leal -16(%ebp), %eax
movl %eax, -12(%ebp)
leal -16(%ebp), %eax
movl %eax, -8(%ebp)
movl -12(%ebp), ea%x
movl %eax, -4(%ebp)
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
我们可以看到只有在对引用类型取地址之后才将a的地址赋值给它。说明c++对引用类型的取地址操作进行了封装。