一、指针:内容是指示一个内存地址的变量;类型是指示编译器怎么解释指针内容指向地址中的内容,以及该内存区域有多大;
例子:
int i = 0;
int * pi = &i;
printf(“pi = %x \n”, pi); // 打印pi的内容: 0x2000
printf(“*pi= %d \n” , *pi); // 打印pi指向地址中的值: 5
printf(“&pi= %x \n”, &pi); // 打印pi的地址: 0x100
从汇编的角度来看,指针是这样的:
int i = 0;
010E139E mov dword ptr [i],0
int * pi = &i;
010E13A5 lea eax,[i]
010E13A8 mov dword ptr [pi],eax
二、数组:是一个单一数据类型对象的集合。其中单个对象没有被命名,通过索引访问。
数组名和指针的区别:数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组。数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量。指向数组的指针则是另外一种变量类型,仅仅意味着数组的存放地址
注意:虽然数组名可以转换为指向其指代实体的指针,但是它只能被看作一个指针常量,不能被修改,如下:
int intArray[10];
intArray++; // 错误
“指针和数组等价”说的是什么?索引操作相同,例如: p[2]; a[2];
三、 引用 ( reference )是一个对象的别名。用对象初始化引用后,对象的名字和引用都指向该对象;
引用是如何实现的? 从汇编语言的角度来看,指针和引用是一样的:
int i = 0;
00E9139E mov dword ptr [i],0
int & ref = i;
00E913A5 lea eax,[i]
00E913A8 mov dword ptr [ref],eax
int * pi = &i;
00E913AB lea eax,[i]
00E913AE mov dword ptr [pi],eax
指针和引用的区别(从C++
使用角度来看):
- 不存在空引用
- 引用要初始化
- 引用初始化后,不能指向另一个对象
这是由编译阶段保证的。
备注
:
1、一个指向非常量的引用不能用字面值或者临时值初始化;但是一个指向常量的引用可以。
例子:
double& d = 12.3; // error!
const double& d = 12.3;
2、由于引用必须初始化,所以使用引用之前不需要测试其有效性,因此使用引用可能会比使用指针效率高。
3、当你实现一个操作符而其语法需求无法由指针完成时,应该选择引用,例如operator[]。operator[]能够出现在一个赋值操作符的左右两边,为了能在左边出现,它的返回值必须是左值,再考虑到使用的方便性,通常把其返回值指定为一个引用类型。
例子:
#include <cassert>
char& String::operator[](int elem) const
{
assert(elem >= 0 && elem <= length());
return _string[elem];
}
4、当你需要考虑不指向任何对象的可能性,或考虑在不同时候指向不同对象的能力时,应该使用指针。
5、引用的所有操作实际上都是应用在它所指的对象上,包括取地址操作符。
6、一些有些特殊的引用举例:
int val = 10;
int* pval = &val;
int*& rpval = pval; // 指针引用
const int i = 10;
const int * const & ref = &i; // 指向常量对象地址的引用