zoukankan      html  css  js  c++  java
  • C++引用和const引用、常量指针、指针常量

    1、引用、常量引用

    引用主要被用做函数的形式参数--通常将类对象传递给一个函数.

    引用在内部存放的是一个对象的地址,它是该对象的别名。引用不占用内存,因为取地址引用的值和被引用变量的地址相同。但是objdump –d xx底层编译器实现其实还是指针。

    (1)引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用.

    int ival = 1092;
    int &re = 1092;  //错误。非常量引用的初始值必须为左值
    int &re = ival;   //ok
    int &re2 = &ival;   //错误。不可用对象的地址初始化引用
    int *pi = &ival;
    int *&pi2 = pi;   //ok。可定义指针引用
    int *&pi3 = &ival; //错误

    (2)一旦引用已经定义,它就不能再指向其他的对象.这就是为什么它要被初始化的原因.

    (3)const引用可以用不同类型的对象初始化(只要能从一种类型转换到另一种类型即可),也可以是不可寻址的值

    double dval = 3.14159;
    //下3行仅对const引用才是合法的,对非const会编译错误
    const int &ir = 1024;
    const int &ir2 = dval;
    const double &dr = dval + 1.0;

    对于不可寻址的值,以及不同型的对象,编译器为了实现引用,必须生成一个临时对象,引用实际上指向该对象,但用户不能访问它。所以上面的通过编译器转为:

    //不可寻址,文字常量
    int tmp1 = 1024;
    const int &ir = tmp1;
    
    //不同类型
    int tmp2 = dval;//double -> int
    const int &ir2 = tmp2;
    
    //另一种情况,不可寻址
    double tmp3 = dval + 1.0;
    const double &dr = tmp3;

    (4)不允许非const引用指向需要临时对象的对象或值,即,编译器产生临时变量的时候引用必须为const(注意

    int iv = 100;
    int *&pir = &iv;//错误,非const引用对需要临时对象的引用
    int *const &pir = &iv;//ok
    
    const int ival = 1024;
    int *&pi_ref = &ival;    //错误,非const引用是非法的
    const int *&pi_ref = &ival;   //错误,需要临时变量,且引用的是指针,而pi_ref是一个非常量指针
    const int * const &pi_ref = &ival;  //正确
    //补充
    const int *p = &ival;
    const int *&pi_ref = p;  //正确

     ********对于const int *const & pi_ref = &iva; 具体的分析如下:*********【仍需学习

    1.不允许非const引用指向需要临时对象的对象或值

    int a = 2;
    int &ref1 = a;// OK.有过渡变量。 
    const int &ref2 = 2;// OK.编译器产生临时变量,需要const引用

     2.地址值是不可寻址的值

    int * const &ref3 = &a;   // OK;

    3.于是,用const对象的地址来初始化一个指向指针的引用

    const int b = 23;
    const int *p = &b; 
    const int *& ref4 = p;
    const int *const & ref5 = &b;   //OK

    const引用的语义

    试图通过此引用去(间接)改变其引用的对象的值时,编译器会报错。保证不会通过此引用间接的改变被引用的对象,但被引用对象还可通过别的方式改变其值。

    与非常量引用区别:常量引用可读不可改,与绑定对象是否为const无关,可绑定到不同但相关的类型对象或左值。非常量引用可读可改,只可与非const对象绑定,只能绑定到与该引用同类型的对象。

    2、常量指针、指针常量

    常量指针:指向常量的指针,能通过常量指针读取内存中数据,但不可修改内存中数据

    声明:const int * p; int const * p;

    注:可以将一个常量的地址赋值给一个对应类型的常量指针,因为常量指针不能够通过指针修改内粗数据。只能防止通过指针引用修改内存中的数据,并不保护指针所指向的对象

    指针常量:指针本身是常量,其本身不可改变,即指向的位置不可改变,但其指向的内容可改变

    声明:int * const p=&a;

    注:指针常量必须在声明的同时对其初始化,不允许先声明一个指针常量随后再对其赋值,这和声明一般的常量是一样的

    区分两者:*为界,左定值,右定向。const在*左边=指针指向的内容不可改变(常量指针),const在*右边=指针指向的位置不可改变(指针常量)

    int a = 1; //定义变量        
    const int b = 2; //定义常量        
    const int *ptr1 = &a; //定义常量指针【并不能通过ptr1修改a的值,但a本身不是常量,a本身是可以修改的】        
    int* const ptr2 = &a; //定义指针常量,必须赋值        
            
    int *ptr3 = &b; //错误,不能把常量的地址赋给指针变量    
    const int* ptr4 = &b; //正确,可以把常量的地址赋给常量指针    
            
    *ptr1 = 3; //错误,间接引用常量指针不可以修改内存中的数据    
    *ptr2 = 4; //正确,间接引用指针常量可以修改内存中的数据
            
    ptr1 = &b; //正确,常量指针可以指向其他变量    
    ptr2 = &b; //错误,指针常量不可以指向其他变量    
            
    const int * const ptr5 = &a; //常量指针常量,即不可以间接引用修改内存数据,也不可以指向别的变量        
    *ptr5 = 5; //错误,不可以间接引用修改内存数据        
    ptr5 = &b; //错误,不可以修改指向的对象

    参考:

    引用  常量指针

  • 相关阅读:
    rabbitmq的安装和使用
    springboot之rabbitmq
    springboot之assembly的文件配置
    Android -- 真正的 高仿微信 打开网页的进度条效果
    香蕉云APP,2016下半年开发日记
    使用 Android Studio 检测内存泄漏与解决内存泄漏问题
    阿里云服务器上配置并使用: PHP + Redis + Mysql 从配置到使用
    PHP 获取 特定时间范围 类
    真实记录疑似Linux病毒导致服务器 带宽跑满的解决过程
    -Android -线程池 批量上传图片 -附php接收代码
  • 原文地址:https://www.cnblogs.com/beixiaobei/p/10446463.html
Copyright © 2011-2022 走看看