【整理】指针和引用初探

大部文章分都有提及到以下几点

相同点

  • 都是地址的概念:指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

不同点

  • 指针是一个实体,而引用仅是个别名
  • 引用只能在定义时被初始一次之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
  • 引用没有const,指针有const,const的指针不可变;
  • 引用不能为空,指针可以为空;
  • “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定)。
  • 指针和引用的自增(++)运算意义不一样;
  • 引用是类型安全的,而指针不是 (引用比指针多了类型检查)

其他疑惑

但是还有些我觉得需要更深入的去理解的问题,引用怎么实现的??

引用没有 const,指针有 const

其实是没有const引用(引用本来就不允许修改),有const指针;但是

1
2
double tmp = 1.0;
double& const rd = tmp;

编译可通过,也可以正常输出,只是const被忽略了。但是

1
2
3
4
void printDouble(const double& rd)
{
cout << rd; // 不需要测试rd,肯定指向一个double值
}

是正常的,这是为了避免参数在函数内被修改(const只能修饰输入参数)。

引用成员占用空间

引用作为成员时,其占用空间与指针相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class B{
char b;
char &c;
};
class C{
char b;
char *c;
};
void main(){
cout<<sizeof(B)<<endl; // 8
cout<<sizeof(C)<<endl; // 8
}

指针传递和引用传递

  • 指针是pass by value方式,不可以修改传入参数的地址,但可以修改该地址指向的值;
  • 引用是pass by reference方式,改变参数的值时就是修改原变量的值。

使用场合

  1. 如果需要指向一个对象,可修改指向另一个对象,并且可能赋空值,声明为指针。
  2. 如果变量肯定指向对象在你的设计不允许变量为空,则声明为引用。
  3. 重载某个操作符时,应该使用引用。最普通的例子是操作符[],返回一个目标对象,其能被赋值。
1
2
v[5] = 10; // 这个被赋值的目标对象就是操作符[]返回的值
*v[5] = 10; // 如果操作符[]返回一个指针

引用和指针实现方式相同

1
2
3
int i=2
int& ref = i;
int *p = &i;

第二三行的汇编实现:

1
2
3
4
5
6
7
8
9
10
8048727: 8d 44 24 1c lea 0x1c(%esp),%eax
// esp寄存器里的变量i的地址传给eax
804872b: 89 44 24 18 mov %eax,0x18(%esp)
//将寄存器eax中的内容(i的地址)传给寄存器中的变量ref,即int& ref=i
8048777: 8d 44 24 1c lea 0x1c(%esp),%eax
// esp寄存器里的变量i的地址传给eax
804877b: 89 44 24 10 mov %eax,0x10(%esp)
//将寄存器eax中的内容(即i的地址)传到寄存器esp中的p

两者实现方式相同,同时也说明了引用是需要占用空间的。

如果对象存在为空的可能性就不可使用引用,否则奔溃或输出是不确定的。

引用优点

  • 不存在指向空值的引用——意味着使用引用的代码效率比使用指针的要高,因为使用引用之前不需要测试它的合法性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void printDouble(const double& rd)
    {
    cout << rd; // 不需要测试rd,肯定指向一个double值
    }
    //相反,指针则应该总是被测试,防止其为空:
    void printDouble(const double *pd)
    {
    if (pd) { // 检查是否为NULL
    cout << *pd;
    }
    }
  • 减少参数传递时调用复制构造函数时的资源消耗。

参考
http://blog.xieyc.com/const-in-detail/
http://www.cnblogs.com/fancyboy2004/archive/2008/12/23/1360810.html
http://blog.csdn.net/dujiangyan101/article/details/2844138
http://blog.jobbole.com/86863/
http://www.cnblogs.com/hoodlum1980/archive/2012/06/19/2554270.html