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

    从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。

    而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。

    在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的:

    指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

    而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

    引用传递和指针传递是不同的,虽然它们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将影响不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。

    为了进一步加深大家对指针和引用的区别,下面我从编译的角度来阐述它们之间的区别:

    程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。

    最后,总结一下指针和引用的相同点和不同点:

    ★相同点:

    ●都是地址的概念;

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

    ★不同点:

    ●指针是一个实体,而引用仅是个别名;

    ●引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;

    ●引用没有const,指针有const,const的指针不可变;

    ●引用不能为空,指针可以为空;

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

    ●指针和引用的自增(++)运算意义不一样;

    ●引用是类型安全的,而指针不是 (引用比指针多了类型检查

     

     

    C++引用与指针的比较 

    引用是C++中的概念,初学者容易把引用和指针混淆一起。 
    一下程序中,n是m的一个引用(reference),m是被引用物(referent)。 
    int m; 
    int &n = m; 
    n相当于m的别名(绰号),对n的任何操作就是对m的操作。 
    所以n既不是m的拷贝,也不是指向m的指针,其实n就是m它自己。 

    引用的规则: 

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

    以下示例程序中,k被初始化为i的引用。 
    语句k = j并不能将k修改成为j的引用,只是把k的值改变成为6。 
    由于k是i的引用,所以i的值也变成了6。 
    int i = 5; 
    int j = 6; 
    int &k = i; 
    k = j; // k和i的值都变成了6; 

    引用的主要功能是传递函数的参数和返回值。 

    C++语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递和引用传递。 

    以下是"值传递"的示例程序。 

    由于Func1函数体内的x是外部变量n的一份拷贝,改变x的值不会影响n, 所以n的值仍然是0。 
    void Func1(int x) 

    x = x + 10; 

    ... 
    int n = 0; 
    Func1(n); 
    cout << "n = " << n << endl; // n = 0 

    以下是"指针传递"的示例程序。 

    由于Func2函数体内的x是指向外部变量n的指针,改变该指针的内容将导致n的值改变,所以n的值成为10。 
    void Func2(int *x) 

    (* x) = (* x) + 10; 

    ... 
    int n = 0; 
    Func2(&n); 
    cout << "n = " << n << endl; // n = 10 

    以下是"引用传递"的示例程序。 

    由于Func3函数体内的x是外部变量n的引用,x和n是同一个东西,改变x等于改变n,所以n的值成为10。 
    void Func3(int &x) 

    x = x + 10; 

    ... 
    int n = 0; 
    Func3(n); 
    cout << "n = " << n << endl; // n = 10 

    对比上述三个示例程序,会发现"引用传递"的性质象"指针传递",而书写方式象"值传递"。 

    实际上"引用"可以做的任何事情"指针"也都能够做,为什么还要"引用"这东西? 
    答案是"用适当的工具做恰如其分的工作"。 

    指针能够毫无约束地操作内存中的任何东西,尽管指针功能强大,但是非常危险。 

    如果的确只需要借用一下某个对象的"别名",那么就用"引用",而不要用"指针",以免发生意外。

  • 相关阅读:
    排序算法(I)冒泡排序
    C#常用类string
    HashMap----工作原理
    Java计算字符串中字母出现的次数
    数据库优化
    线程和进程的区别(详细)
    SpringMVC工作原理
    jsp运行原理及运行过程
    一个公告
    SR
  • 原文地址:https://www.cnblogs.com/xiawen/p/3311816.html
Copyright © 2011-2022 走看看