`

C++指针和引用

    博客分类:
  • C++
 
阅读更多

首先,我在网上搜索了下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++对引用类型的取地址操作进行了封装。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics