zoukankan      html  css  js  c++  java
  • 指针和引用的区别和联系

    这个问题一直很纠结,今天对此进行一些整理,主要是参考《高质量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节

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

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

     

  • 相关阅读:
    Gridview利用DataFormatString属性设置数据格式
    PowerDesigner15 逆向工程
    JS实现动态显示当前时间(12/24小时制)(转载Mr.Think)
    如何判断Javascript对象是否存在
    PHP学习(一):判断数组中的值是否包含某字符
    JavaScript显示剩余时间
    Hibernate:a different object with the same identifier value was already associated wit异常解决
    excel含文字求和
    excel去掉最高分
    excel保护
  • 原文地址:https://www.cnblogs.com/ChengDongSheng/p/3392058.html
Copyright © 2011-2022 走看看