美文网首页C++学习笔记
C++中关于指针与引用

C++中关于指针与引用

作者: 南方老F | 来源:发表于2018-06-29 15:27 被阅读0次
    摘抄自————《C++ Primer中文第五版》
    

    1.引用(reference):为对象起了另外一个名字,引用类型引用(refers to)另外一种类型。通过将声明符写成 &d (&:取地址操作符)的形式来定义引用类型,其中d是声明的变量名:

    int ival = 1024;
    int &referVal = ival;   //refVal指向ival(是ival的另一个名字) 
    int &refaVal2;   //错误:引用必须被初始化
    

    注意:
      a. 引用必须被初始化,程序把引用和它的初始值对象一直绑定在一起。因为无法令引用重新绑    定到另外一个对象,因此引用必须初始化。
      b. 引用并没有实际地址,只是为一个已存在的对象所起的另外一个名字。
      c. 对引用的所有操作都是在与之绑定的对象上进行的。
      d. 引用的类型与绑定的对象类型必须一致。

    2. 指针(pointer):是指 “ 指向(point to) ” 另外一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。定义指针类型的方法将声明符写成 *d 的形式,其中 d 是变量名。

    int i = 10;
    int *ipl = &i;   //ipl是指向int型对象的指针
    int *pr, *pi;     //定义两个int型指针
    

    2.1 指针与引用的不同点:

      其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。

      其二,指针无须再定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。

    2.2 指针值:

    a. 指向一个对象。
    b. 指向紧邻对象对象所占空间的下一个位置。
    c. 空指针,意味着指针没有指向任何对象。
    d. 无效指针,也就是上述情况之外的其他值。

    2.3 某些符号有多重含义

    int i = 42;
    int &r = i;  // &紧随类型名出现,因此是声明的一部分,r是一个引用
    int *p;  // *紧随类型名出现,因此是声明的一部分,p是一个指针
    p = &i;  // &出现在表达式中,是一个取地址符
    *p = i;  // *出现在表达式中,是一个解引用符
    int &r2 = *p;  // &是声明的一部分, *是一个解引用符
    

    2.4 空指针

      空指针(null pointer)不指向任何对象,在试图使用一个指针之前代码可以首先检查是否为空。以下是几个生成空指针的方法:

    int *p1 = nullptr;  //C++11新标准方法。等价于 int *p1 = 0;
    int *p2 = 0;  //直接将p2初始化为字面常量0
    //需要首先 #include cstdlib
    int *p3 = NULL;  // 等价于 int *p3 = 0;
    

    2.5 void* 指针

      void *指针是一种特殊的指针类型,可用于存放任意对象的地址。一个void * 指针存放着一个地址,这一点和其他指针类似。不同的是。我们对该地址中到底是个什么类型的对象并不了解:

    double obj = 3.14, *pd = &obj;
    // 正确:void* 能存放任意类型对象的地址
    void *pv = &obj;  // obj可以是任意类型的对象
    pv = pd;   // pv可以存放任意类型的指针
    

    2.6 指向指针的指针

    int ival = 1024;
    int *pi = &ival;  // pi 指向一个int型的数
    int **ppi = π  // ppi 指向一个int型的指针
    

      这里pi是指向int型数的指针,而ppi是指向int型指针的指针,如图:


    指向指针的指针.png

      解引用 int 型指针会得到一个int型的数,同样,解引用指向指针的指针会得到一个指针。此时为了访问最原始的那个对象,需要对指针的指针做两次解引用:

    cout  << "The value of ival\n"
          << "direct value: " << ival << "\n"
          << "indirect value: " << *pi << "\n"
          << "double indirect value: " << **ppi
          << endl;
    

      该程序使用三种不同的方式输出了变量 ival 的值: 第一种直接输出;第二种通过int型指针pi输出;第三种两次解引用ppi,取得ival的值。

    2.7 指向指针的引用
      引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以存在对指针的引用:

    int t = 42;
    int *p;  // p 是一个int型指针
    int *&r = p;  // r是一个对指针p的引用
    
    r = &i;  // r引用了一个指针,因此给r赋值&i就是令p指向i
    *r = 0;  // 解引用 r 得到 i,也就是 p 指向的对象,将 i 的值改为0
    

      要理解 r 的类型到底是什么,最简单的办法是从右往左阅读 r 的定义。离变量名最近的符号(此例中是 &r 的符号是 &)对变量的类型有最直接的影响,因此 r 是一个引用。声明符的其余部分用以确定 r 引用的类型是什么,此例中的符号 * 说明 r 引用的是一个指针。最后,声明的基本数据类型部分指出 r 引用的是一个 int 指针。

    因此这里 int *&r = p;
    应该看成是 对 int*(int型的指针)的引用,所以对 p指针的操作和对 r 引用的操作是一样的。

    2.8 另外: 关于& 和 *& 理解

    int i = 100;
    int *p = &i;
    int &pr = *p;  // *是一个解引用符,由*得到指针p所指的对象
    int *&pi = p;
    

    这里 &pr 和 *&pi 表面上看值都是一样的,但是有一点不同

    pr 是指针p所指对象的引用
    pi 是指针p的引用

      假如p指针指向的是一个数组,那么 pr只能访问p的首元素(单一对象),而pi则可以访问p的整个数组(数组的地址)。

    2.9 const 指针
      指针是对象而引用不是,所以指针本身可以定为常量。常量指针(const pointer)必须初始化,一旦初始化完成,则它的值(也就是存放在指针中的那个地址)就不能再改变了。把 * 放在 const 关键字之前用以说明指针是一个常量,这样的书写形式隐含着一层意味,即不变的是指针本身的值而非指向的那个值:

    int errNumb = 0;
    int *const curErr = &errNumb;  // curErr 将一直指向 errNumb
    const double pi =3.14159;  
    const double *const pip = &pi;  //pip是一个指向常量对象的常量指针
    

      要想弄清楚上述声明的含义,最有效的办法是从右向左阅读。离 currErr 最近的符号是 const,意味着 currErr 本身是一个常量对象,对象的类型由声明符的其余部分确定。声明符中的下一个符号是*,意思是 currErr 是一个常量指针。最后,该声明语句的基本数据类型部分确定了常量指针指向的是一个 int 对象。与之相似,我们也能推断出,pip是一个常量指针,它指向的对象是一个双精度浮点型常量。
      指针本身是一个常量并不意味着不能通过指针修改其所指对象的值,能否这样做完全依赖于所指对象的类型。例如,pip 是一个指向常量的常量指针,则不论是 pip所指的对象值还是pip自己存储的那个地址都不能改变。相反的,curErr 指向的是一个一般的非常量整数,那么就完全可以用 curErr 去修改 errNumb 的值:

    *pip = 2.72;  // 错误:pip是一个指向常量的指针
    // 如果 curErr 所指的对象(也就是errNumb)的值不为 0 
    if (*curErr) 
    {
      errorHandler();
      *curErr = 0;  //正确:把curErr所指的对象的值重置
    }
    

    相关文章

      网友评论

        本文标题:C++中关于指针与引用

        本文链接:https://www.haomeiwen.com/subject/pikayftx.html