指针和引用的区别和联系

这个问题一直很纠结,今天对此进行一些整理,主要是参考《高质量C++编程指南》和《More Effective C++》

第一层:

先从表面理解一下指针和引用之间的区别:

(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。 (2)不能有NULL 引用,引用必须与合法的存储单元关联(指针则可以是NULL)。 (3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。

摘自《高质量C++编程指南》6.6节

第二层:

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

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

下面这段代码对此进行验证

//main.h
class A
{
private:
    int data;
    std::string& rs;
    std::string s;
public:
    A(int num,std::string s1):data(num),rs(s1),s(s1){};
    int add(const A& a,const A& b)
    {
        int num=data+a.data+b.data;
        return num;
    }
};

class B
{
private:
    std::string s;
public:
    B(std::string s1):s(s1){};
};
#include <iostream>
#include <string>
#include "main.h"

using namespace std;

void main(void)
{
    A a(1,"a"),b(2,"b");
    A* Aptr=&a;
    A& Aref=a;
    B c("c");
    B& Bref=c;
    cout<<"ptr="<<sizeof(Aptr)<<"	reference="<<sizeof(Aref)<<"	Bref="<<sizeof(Bref)<<endl;
    system("pause");
}

输出结果:Aptr=4,Aref=40,Bref=32(在VS2010下编译)

何时使用指针,何时使用引用:

在以下情况下你应该使用指针

1.是你考虑到存在不指向任何对象的可能。在这种情况下,你能够设置指针为空;

2.是你需要能够在不同的时刻指向不同的对象。在这种情况下,你能改变指针的指向。

在以下情况下你应该使用指针

1.如果总是指向一个对象,并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。 2.还有一种情况  就是当你重载某个操作符时,你应该使用引用。

string s2("Clancy");
string& rs = s1; // rs 引用s1
string *ps = &s1; // ps 指向s1
rs = s2; // rs 仍旧引用s1,
// 但是s1 的值现在是
// "Clancy"
ps = &s2; // ps 现在指向s2;
// s1 没有改变

摘自《More Effective C++》条款一

还需要主要一点的是对引用赋空值是很危险的,但是编译器貌似做了这种处理,因此在运行时会报错

char* pc=0;
char& rc=*pc;

第三层:

为什么C++语言中既有指针也有引用?

第一,为什么有了引用还需要指针呢? 这个比较简单,因为Bjarne Stroustrup要让C++借C的势,必然要支持指针了。

第二,为什么有了指针还需要引用呢? 这个就比较复杂了,首先一开始C++是没有引用的。比如说:this,被定义为了指针,而不是引用。后来加入了引用的原因主要是为了支持operator overloading。

指针,算是一种变相的“引用”,但依然是call by value。区别在于:指针需要函数的调用者显式地来表示“引用”,比如说使用取地址符(&)把变量转换成指针。 引用,是call by reference,区别在于:引用不需要函数的调用者显式的来表示。根据所调用的函数,变量的名字可以分别解释为value或者reference。

更加深入了解参阅http://www.cnblogs.com/volatile/archive/2012/06/02/Pointer_vs_Reference_in_CPP.html

这篇博客写的非常好,下面这种情况不会编译通过

int add(const A& a,const A& b)
{
    int num=data+a.data+b.data;
    return num;
}

int add(const A a,const A b)
{
    int num=data+a.data+b.data;
    return num;
}

原因当然是对重载函数调用不明确了~

第四层:

这层多少是从设计哲学来考虑,这段话说的非常好,如醍醐灌顶

实际上“引用”可以做的任何事情“指针”也都能够做,为什么还要“引用”这东西?

答案是“用适当的工具做恰如其分的工作”。 指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。 就象一把刀,它可以用来砍树、裁纸、修指甲、理发等等,谁敢这样用? 如果的确只需要借用一下某个对象的“别名”,那么就用“引用”,而不要用“指针”, 以免发生意外。比如说,某人需要一份证明,本来在文件上盖上公章的印子就行了,如 果把取公章的钥匙交给他,那么他就获得了不该有的权利。

摘自《高质量C++编程指南》6.6节

总结:虽然没有自己的东西,但是总结归纳别人的知识,也从中学到了很多东西,并且确实是一件很费神的事情。

指针使用更加灵活,从某种角度来说权利也比引用大,但是权利大也会带来一些问题,引用权利小,但是适用就好,不要给过多的权限给某个操作!

 

原文地址:https://www.cnblogs.com/ChengDongSheng/p/3392058.html