`

指针和引用的区别

阅读更多

一、
C++中引用和指针的区别
指针初始化的时候,可以指向一个地址,也可以为空。
引用必须初始化为另一个变量.
 int ival = 1024;
 int *pi  = &ival; // a pointer
 int &rval = ival; // a reference

二、
估计很多人在编写C++程序都或多或少的会用到pointer 和 reference这两种东西,但是他们两者到底有什么样的区别和联系呢,相信大多数人是不太了解的,今天我就两者的区别和联系从实际程序的角度来加以区别。
C/C++中的指针其实就是一个变量,和其他类型的变量是一个样子的,它是一个占用四字节的变量(32位机上),它与其他变量的不同之处就在于它的变量值是一个内存地址,指向内存的另外一个地方。reference我的理解就是一个别名,它和linux操作系统上的alias是一个样子的。再者,一个pointer变量可以指向NULL,表示它不指向任何变量地址,但是reference必须在声明的时候就得和一个已经存在的变量相绑定,而且这种绑定不可改变。下面是我写的一段程序来验证pointer与reference的区别和联系的,希望能对大家理解pointer & reference的区别和联系有所帮助:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
 int ival = 1024;
 int *pi  = &ival; // a pointer
 int &rval = ival; // a reference
 int jval = 4096;
 int xval = 8192;
 cout << "ival = " << ival << "\t";
 cout << "&ival = " << &ival << "\t";
 cout << endl;
 cout << "pi = " << pi << "\t";
 cout << "&pi = " << &pi << "\t";
 cout << "*pi = " << *pi << "\t";
 cout << endl;
 cout << "rval = " << rval << "\t";
 cout << "&rval = " << &rval << "\t";
 cout << endl;
 cout << "jval = " << jval << "\t";
 cout << "&jval = " << &jval << "\t";
 cout << endl;

 // change the values of the reference and the pointer
 pi = &jval;
 rval = jval;

 // print the changes
 cout << endl;
 cout << "ival = " << ival << "\t";
 cout << "&ival = " << &ival << "\t";
 cout << endl;
 cout << "pi = " << pi << "\t";
 cout << "&pi = " << &pi << "\t";
 cout << "*pi = " << *pi << "\t";
 cout << endl;
 cout << "rval = " << rval << "\t";
 cout << "&rval = " << &rval << "\t";
 cout << endl;
 cout << "jval = " << jval << "\t";
 cout << "&jval = " << &jval << "\t";
 cout << endl;

 cout << endl;
 *pi = xval;
 cout << "pi = " << pi << "\t";
 cout << "&pi = " << &pi << "\t";
 cout << "*pi = " << *pi << "\t";
 cout << endl;
 cout << "jval = " << jval << "\t";
 cout << "&jval = " << &jval << "\t";
 cout << endl;

 return 0;
}

一次的执行结果如下:
ival = 1024 

&ival = 0012FF7C
pi = 0012FF7C   &pi = 0012FF78  *pi = 1024
rval = 1024     &rval = 0012FF7C
jval = 4096     &jval = 0012FF70

 

ival = 4096     &ival = 0012FF7C
pi = 0012FF70   &pi = 0012FF78  *pi = 4096
rval = 4096     &rval = 0012FF7C
jval = 4096     &jval = 0012FF70

pi = 0012FF70   &pi = 0012FF78  *pi = 8192
jval = 8192     &jval = 0012FF70

如果有兴趣的话也可以使用其他类型的变量来测试,并且打印出各个变量占用内存的大小,我在这里就不把具体的程序贴出来了。

三、 C++点滴:向函数中传递指针和传递指针的引用的区别:

如果是传递指针,那么回先复制该指针,在函数内部使用的是复制后的指针,这个指针与原来的指针指向相同的地址,如果在函数内部将复制后的指针指向了另外的新的对象,那么不会影响原有的指针;
但是对于传递指针应用,如果将传递进来的指针指向了新的对象,那么原始的指针也就指向了新的对象,这样就会造成内存泄漏,因为原来指针指向的地方已经不能再引用了,即使没有将传递进来的指针指向新的对象,而是在函数结束的时候释放了指针,那么在函数外部就不能再使用原有的指针了,因为原来的内存已经被释放了

对象指针和对象引用

指向类的成员的指针

    
C++中,可以说明指向类的数据成员和成员函数的指针。

    
指向数据成员的指针格式如下:

    <
类型说明符><类名>::*<指针名>

指向成员函数的指针格式如下:

    <
类型说明符>(<类名>::*<指针名>)(<参数表>)

    
例如,设有如下一个类A


    class A
    {
    public:
        int fun (int b) { return a*c+b; }
        A(int i) { a=i; }
        int c;
    private:
         int a;
    };

    
定义一个指向类A的数据成员c的指针pc,其格式如下:
    int A:: *pc = &A::c;
再定义一个指向类A的成员函数fun的指针pfun,其格式如下:
    int (A:: *pfun)(int) = A::fun;

    
由于类不是运行时存在的对象。因此,在使用这类指针时,需要首先指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下:

    A a;
    a.*pc = 8;

    
其中,运算符.*是用来对指向类成员的指针来操作该类的对象的。
    
如果使用指向对象的指针来对指向类成员的指针进行操作时,使用运算符->*。例如:
    A *p = &a;    //a

是类A的一个对象,p是指向对象a的指针。
    p ->* pc = 8;
    
让我们再看看指向一般函数的指针的定义格式:

    <
类型说明符>*<指向函数指针名>(<参数表>)

    
关于给指向函数的指针赋值的格式如下:


    <
指向函数的指针名>=<函数名>

    
关于在程序中,使用指向函数的指针调用函数的格式如下:


    (*<
指向函数的指针名

>)(<实参表>)

    
如果是指向类的成员函数的指针还应加上相应的对象名和对象成员运算符。


    
下面给出一个使用指向类成员指针的例子:

    #include <iostream.h>
    class A
    {
    public:
    A(int i) { a=i; }
    int fun(int b) { return a*c+b; }
    int c;
    private:
    int a;
    };

    void main()
    {
    A x(8);        //
定义类A的一个对象x
    int A::*pc;    //
定义一个指向类数据成员的指针
pc
    pc=&A::c;    //
给指针pc赋值

    x.*pc=3;    //
用指针方式给类成员c

赋值为3
    int (A::*pfun)(int);    //
定义一个指向类成员函数的指针
pfun
    pfun=A::fun;        //
给指针pfun赋值

    A *p=&x;        //
定义一个对象指针p,并赋初值为x
    cout<<(p->*pfun)(5)<<endl;    //
用对象指针调用指向类成员函数指针pfun指向的函数

    }

    
以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。

对象指针和对象引用

作函数的参数

    1. 
对象指针作函数的参数

    
使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针作函数参数有如下两点好处:
    (1) 
实现传址调用。可在被调用函数中改变调用函数的参数对象的值,实现函数之间的信息传递。
    (2) 
使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少时空开销。

    
当形参是指向对象指针时,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针作函数参数。

    #include <iostream.h>
    class M
    {
    public:
        M() { x=y=0; }
        M(int i, int j) { x=i; y=j; }
        void copy(M *m);
        void setxy(int i, int j) { x=i; y=j; }
        void print() { cout<<x<<","<<y<<endl; }
    private:
        int x, y;
    };

    void M::copy(M *m)
    {
    x=m->x;
    y=m->y;
    }

    void
fun(M m1, M *m2);
    void main()
    {
    M p(5, 7), q;
    q.copy(&p);
    fun(p, &q);
    p.print();
    q.print();
    }

    void fun(M m1, M *m2)
    {
    m1.setxy(12, 15);
    m2->setxy(22,25);
    }

    输出结果为:
    5,7
    22,25
    
从输出结果可以看出,当在被调用函数fun中,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。

    2. 
对象引用作函数参数

    
在实际中,使用对象引用作函数参数要比使用对象指针作函数更普遍,这是因为使用对象引用作函数参数具有用对象指针作函数参数的优点,而用对象引用作函数参数将更简单,更直接。所以,在C++编程中,人们喜欢用对象引用作函数参数。现举一例子说明对象引用作函数参数的格式。

    #include <iostream.h>
    class M
    {
    public:
    M() { x=y=0; }
    M(i
nt i, int j) { x=i; y=j; }
    void copy(M &m);
    void setxy(int i, int j) { x=i; y=j; }
    void print() {cout<<x<<","<<y<<endl; }
    private:
    int x, y;
    };

    void M::copy(M &m)
    {
    x=m.x;
    x=m.y;
    }

    void fun(M m1, M &m2);

    void main()
    {
    M p(5, 7), q;
    q.copy(p);
    fun(p, q);
    p.print();
    q.print();
    }

    void fun(M m1, M &m2)
    {
    m1.setxy(12, 15);
    m2.setxy(22, 25);
    }

    该例子与上面的例子输出相同的结果,只是调用时的参数不一样。

3
this指针

    this
指针是一个隐含于每一个成员函数中的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。

    
当对一个对象调用成员函数时,编译程序先将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员时,由隐含作用this

分享到:
评论

相关推荐

    AccessControl-5.3-cp39-cp39-manylinux_2_5_i686.whl.zip

    AccessControl-5.3-cp39-cp39-manylinux_2_5_i686.whl.zip

    AccessControl-6.1-cp39-cp39-manylinux_2_5_x86_64.whl.zip

    AccessControl-6.1-cp39-cp39-manylinux_2_5_x86_64.whl.zip

    基于S128单片机智能赛车的设计

    本文的目的是实现基于单片机智能赛车的设计,它是一种以规定的汽 车模型为载体,采用位微控制器为核心控制模块,通过自主设计电源电路,电 机驱动电路、道路光电传感器电路,硬件部分合理布局,同时编写配套程序,使其能够自 主识别路径的模型车。比赛时它能在规定赛道上,以最短时间跑完全程,且取得较好成绩, 论文整体包括:绪论,系统总体方案设计,车模机械部分设计改造,硬件电路部分设计制 作,软件部分设计,系统调试六章内容。 本文简单介绍了国内外智能车的发展概况,“飞思卡尔杯”智能车大赛起源以及我国 “飞思卡尔”杯全国智能车竞赛盛况。详细地阐述了该款智能赛车软硬件设计、制作、调试 的具体方法和过程。并对转向舵机,直流电机调速信号的控制做了一些研究。 主控模块,作为整个智能汽车的“大脑”,光电传感器、光电编码器 等传感器的信号,根据控制算法做出控制决策,驱动直流电机和伺服电机完成对智能汽车 的控制。传感器模块,是智能汽车的“眼睛”,可以通过一定的前瞻性,提前感知前方的 赛道信息,为智能汽车的“大脑”做出决策提供必要的依据和充足的反应时间。总之,电 源模块,为整个系统提供合适而又充足的能源。电机驱动模块,驱

    AX3_Mercadopago-0.3.6-py3-none-any.whl.zip

    AX3_Mercadopago-0.3.6-py3-none-any.whl.zip

    RealChar原生版本

    数字人对话源码原生版本,为了更好地阅读源码可参考此版本,具体源码解析文章见:https://blog.csdn.net/eaglewood2005/article/details/137786309

    Acquisition-4.11-cp38-cp38-manylinux_2_17_aarch64.whl.zip

    Acquisition-4.11-cp38-cp38-manylinux_2_17_aarch64.whl.zip

    2024年Java高工面试题 2024年Java高工面试题 2024年Java高工面试题

    2024年Java高工面试题 JVM虚拟机:堆、方法区(元空间)、栈(线程)、本地方法栈、程序计数器 栈帧:局部变理表、操作数栈、动态链接、方法出口 对象组成:对象头(Mark Word、KlassPointer类型指针、数组长度)、实例数据、对齐填充(8个字节)CMS:初始标记、并发标记、重新标记、并发清理、并发重置 G1:初始标记、并发标记、最终标记、筛选回收1、spring是一个快速开发框架,帮助程序员来管理对象 2、设计模式的应用、并发安全的实现、面向接口的设计等 3、在创建Spring容器,也就是启动Spring时: (1)首先会进行扫描得到所有的Bean Definition对象,并存在一个MAP中 (2)然后筛选出非懒加载的单例Bean Definition 对象进行创建Bean,多实例的Bean会在每次获取Bean时利用Bean Definition去创建 (3)利用Bean definition创建Bean就是Bean的创建生命周期,包括:合并Bean Definition 推断构造方法、实例化、属性填充、初始化前、初始化、初始化后等其中AOP就是发生在初始化后这一步

    Python机器学习机器学习十大算法英文文档SVM

    Python机器学习机器学习十大算法英文文档SVM提取方式是百度网盘分享地址

    基于最近邻分类器KNN的手写数字识别程序,包含GUI界面

    亲测可用。 算法基于最近邻分类器(K-Nearest Neighbors, KNN)的思想。而是遍历所有已知字符的特征向量,找到距离输入特征向量最近的一个,并将其对应的字符作为识别结果。

    Python机器学习机器学习十大算法英文文档CART

    Python机器学习机器学习十大算法英文文档CART提取方式是百度网盘分享地址

    pycharm-08-tcp服务端程序的开发.ev4.rar

    pycharm-08-tcp服务端程序的开发.ev4.rar

    Acquisition-4.13-cp310-cp310-manylinux_2_17_aarch64.whl.zip

    Acquisition-4.13-cp310-cp310-manylinux_2_17_aarch64.whl.zip

    2024-2030全球与中国住宅太阳能光伏组件市场现状及未来发展趋势.docx

    2024-2030全球与中国住宅太阳能光伏组件市场现状及未来发展趋势

    第2章 方程求根.pdf

    第2章 方程求根

    Python安装文件(MAC苹果系统)

    0.Python安装教程-Mac、pycharm-community-2022.2.1、python-3.10.7-macos11

    AX3_model_extras-1.4.1-py3-none-any.whl.zip

    AX3_model_extras-1.4.1-py3-none-any.whl.zip

    调优初始jmeter脚本

    调优初始jmeter脚本

    Ent animated character 恩特动画角色 游戏树怪模型带动画资源包unitypackage项目

    Ent animated character 恩特动画角色 游戏树怪模型带动画资源包unitypackage项目 支持Unity版本2019.2.18或更高 动画 走 闲置的 空闲时间长 空闲_长_2 攻击 损害 死亡 纹理 512x512 多边形 3093

    计算机设计 - VB+ACCESS智能公交考勤系统管理软件设计(LW),保证可靠运行,毕业生可参考,免费资源下载

    VB+ACCESS智能公交考勤系统管理软件设计项目是一个基于Visual Basic(VB)编程语言和ACCESS数据库技术的考勤管理解决方案。该项目旨在利用现代信息技术,为公交公司的考勤管理提供智能化、自动化的工具,提高考勤工作的效率和准确性。 在软件设计过程中,我们首先对公交公司的考勤管理需求进行了深入的分析,明确了软件的功能模块和数据结构。基于这些需求,我们利用VB的编程功能,设计了用户友好的界面和交互逻辑,使用户能够方便地进行考勤信息的录入、查询和统计。 同时,我们利用ACCESS数据库技术,建立了考勤信息的存储和管理机制。通过合理的数据库设计,我们实现了对考勤数据的快速查询、更新和备份,保证了数据的完整性和安全性。 此外,软件还具备智能化的考勤分析功能,能够根据考勤数据自动生成各类报表和图表,帮助管理人员更好地了解员工的出勤情况,优化考勤管理制度。 最后,我们撰写了详细的论文,对智能公交考勤系统管理软件的设计思路、实现过程以及应用效果进行了全面阐述,为软件的开发和应用提供了理论支持和实践指导。

    Android L代码编译及版本下载说明-V1.0

    Android L代码编译及版本下载说明-V1.0

Global site tag (gtag.js) - Google Analytics