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


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

    写在前面的话,本文是基于C++03写的。并不涉及C++11里面的概念,比如Rvalue references

    引用和指针有何区别?这是个经常会被提到的问题。也有诸多的博客来分析其实引用就是指针。
    即使两者的底层实现都一样,都是基于地址,然而我认为这两者是截然不同的概念。

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

    不过本篇博客,并不是用来谈两者的区别或者实现。而是说为什么C++同时需要这两个看起来很像的东西。
    问题分两方面:

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

    第二,为什么有了指针还需要引用呢?
    这个就比较复杂了,首先一开始C++是没有引用的。比如说:this,被定义为了指针,而不是引用。后来加入了引用的原因主要是为了支持operator overloading。这在Bjarne Stroustrup那本书《The Design and Evolution of C++》和他的C++ FAQ里面都提到了。
    细说开来,假设C++里面没有引用,而只有指针,会有什么样的问题。
    如果用指针来overload operator的话,就像:

    ClassFoo operator+( const ClassFoo *, const ClassFoo * )

    使用的时候只能是 &a + &b,这和我们通常的写法 a + b 不太一样,看上去不太习惯。
    还可以进一步假设,也可以就写成 a + b,让编译器来根据operator+的类型来解释a和b的类型。如果operator+的参数是值,那就解释成值;如果是指针,就解释成地址。这和现在C++里面把名字解释成值或者引用是一个道理。
    这样做的后果是,指针和值不能重载了,比如说下面这两个函数,就无法通过编译。因为可以把a和b同时解释成value和pointer。

    void foo(ClassFoo*);
    void foo(ClassFoo);

    针对同一个函数,根据是value还是pointer有不同的实现,这是个相对普遍的需求。而且在C语言中,指针已经有了明确的定义,并不适合赋予它其他的概念。
    而引入引用的概念,既可以满足overload operator,也不失重载value和pointer的灵活性。虽然引用也面对一个问题,即值和引用不能重载了,不过也没什么情况需要重载这两者。

    除了支持operator overloading,引用还带来一个指针无法替代的特性: 引用临时对象。因为引用必须在定义的时候就赋值,以后无法更改。比如下面的代码

    class ClassFoo{
    public :
           ClassFoo( const char *){};
    };
     
    const ClassFoo* g_ClassFoo = NULL;
    void foo(const ClassFoo& r){};
    void bar(const ClassFoo* p){
           g_ClassFoo = p;
    };
    foo( "abc" ); 
    bar( "def" );

    foo的调用是没有问题的,"abc"生成的临时对象只会存在于函数的调用期间。
    bar的调用是有问题,指针没法指向临时对象的,因为指针是可以把这种关系传递出去的。

    综上所述,C++必须同时有指针和引用这两个概念。

    顺便提一下,还有个被问到烂的问题,指针和引用那个好,该用哪一个?
    可以参考,Google C++ Style Guide 和 c++-faq-lite,我就不吐槽了。

  • 相关阅读:
    Mirco2440核心板设计思考
    linux 第一次获得root权限
    MakeFile 文件详解
    windows下编辑过的文件在Linux下用vi打开行尾会多出一个^M符号
    linux信息查找
    ubuntu不能正常使用make menuconfig的解决方案
    Linux 解压/压缩操作命令
    Linux 文件/文件夹操作命令
    Linux内核开发基础
    计算文件夹的大小
  • 原文地址:https://www.cnblogs.com/lexus/p/2559102.html
Copyright © 2020-2023  润新知