zoukankan      html  css  js  c++  java
  • 指针

    【1】如何理解指针?

    指针,就是地址值。强调一点,计算机世界就是对现实的一种精确模拟。那么,既然是模拟,现实中什么是指针呢?嗯,对了,大概你已经想到

    了,就是可以等价于你家的门牌号。如果你是一个学生的话,那就是你的座位号;如果你刚买了一座别野(别墅的雅称,其实这个名字更有意义,因

    为如果人人都住别墅去了的话,人与人之间就没有那么多的沟通,也就相当于野人了,所以叫“别野”),那么指针就是你家的别野号。

    由于现实的地址也是多种多样的,所以在计算机世界里,指针也是很多类别的。

    【2】各种指针有何特性?

    (1)一般指针

    示例代码以及相关分析如下:

     1 #include<iostream>
     2 using namespace std;
     3 
     4 void main()
     5 {
     6     int a = 10;    //定义int型变量a并赋值为10
     7     cout<<"&a="<<&a<<endl;    //输出变量a的地址
     8     int *p = NULL;  //定义指针变量p.此指针变量的类型为int *.也就是指向整型变量的指针。由于暂时不确定指向,赋值空NULL
     9     int *pa = NULL,b;  //这种写法必须要注意:“*”符号只对pa有效,也就是说pa才是指针变量。b是一个整型变量。
    10     pa = &a;    //pa这个指针变量指向了a这个整型变量。注意这里有一个类型匹配的问题。即就是:赋值兼容性原则。
    11     cout<<"pa="<<pa<<endl;
    12     b = 20;
    13     *pa = b;
    14     //pa的内容就是pa这个指针变量的另外一个值,此句主要是为解释指针的双值性。执行这一句,*pa原来的内容就会变为b变量的值,即就是20。这就是运行结果a=20的依据。
    15     cout<<"pa="<<pa<<endl;
    16     cout<<"a="<<a<<endl;
    17 }
    18 //The  result of  this
    19 /* 
    20 &a=0x0012FF7C
    21 pa=0x0012FF7C
    22 pa=0x0012FF7C
    23 a=20
    24 */

    (2)函数指针

    <1>可以把一个指针声明为一个指向函数的指针。示例代码如下:

    1 int   fun1(char *,int);
    2 int  (*pfun1)(char *,int);
    3 pfun1 = fun1;

    声明函数fun1。再声明函数fun1的指针pfun1。注意观察指针的类型以及指针指向的类型。

    再给函数指针赋值。注意这里也是必须要遵守赋值兼容原则。

    <2>通过函数指针调用函数的两种形式过程说明。示例代码如下:

     1 #include<iostream.h>
     2 int add(int a,int b)
     3 {
     4     return a+b;
     5 }
     6 int max(int a,int b)
     7 {
     8     return a>b? a:b;
     9 }
    10 void main()
    11 {
    12     int (*fun)(int,int);     //函数指针    fun为类型名
    13     fun=add;
    14     cout<<fun(12,23)<<endl;
    15     fun=max;
    16     cout<<(*fun)(23,34)<<endl;
    17 }
    18 /*
    19 运行结果:
    20 35
    21 34
    22 */

    过程说明:

    第十二行:一个函数指针,fun为函数指针变量名。

    第十三行:赋值为add函数

    第十四行:调用函数fun()。通过指针实现如上所示。

    第十五行:赋值为max函数

    第十六行:调用函数max()。通过指针实现如上所示。

    (3)this指针

    面向对象编程的关键是类的设计,而类设计的难处主要在于它是很抽象的,抽象怎么解释呢?

    举个生活中的例子。比如说:“XXX,你去给我买两斤水果,回来再给你还钱。”好了,这就是个很具体的例子。

    那么,这个水果到底指的是什么东东?是苹果?是梨?是橘子?是......总之,这个概念太抽象了。

    但是,水果还真是一个类别,你看大街上什么餐饮店,什么水果超市,什么鞋店。什么书店等等的。

    嗯,高度抽象都是有一种共同行为的东西!这就是所有面向对象程序设计书中提到的那个行为的概念。

    而所谓的属性是指本身的相关特性。好,既然同一个类中所衍生的对象都是具有相同行为的,只不过属性彼此不同而已。

    为了节省空间,方法也就是所谓的成员函数在内存中也就只有一份拷贝。

    那么,这也就存在一个问题,各个对象公用一份拷贝的成员函数,到底是哪个对象调用成员函数?就取决于对象的this指针。

    其实,在每个成员函数【除过静态的】的参数部分,都有一个隐藏的this指针,而且它是这样子定义的:class * const this

    示例代码如下:

     1 #include<iostream.h>
     2 class Test
     3 {
     4 private:
     5     int value;
     6 public:
     7     Test(int x=0):value(x)
     8     {}
     9     ~Test()
    10     {}
    11     void fun()
    12     {      // void fun(Test * const this)
    13         cout<<this->value<<endl;
    14     }
    15 };
    16 
    17 void main()
    18 {
    19     Test t1(10),t2(100);
    20     t1.fun();
    21     // fun(&t1);本质上应该是这样的过程
    22     t2.fun();
    23     // fun(&t2);本质上应该是这样的过程
    24 }
    25 //The  result  of  this  
    26 /*
    27 10
    28 100
    29 */

    【3】关于指针的以下应用分析:

    从变量名处起,根据运算符优先级结合,一步一步分析

     1 int   p;  //这是一个普通的整型变量
     2 
     3 int  *p;  //首先从P 处开始,先与*结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int 型.所以P是一个返回整型数据的指针
     4 
     5 int  p[3];  //首先从P 处开始,先与[]结合,说明P 是一个数组,然后与int 结合,说明数组里的元素是整型的,所以P 是一个由整型数据组成的数组
     6 
     7 int  *p[3]; //首先从P 处开始,先与[]结合,因为其优先级比*高,所以P是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组
     8 
     9 int  (*p)[3]; //首先从P 处开始,先与*结合,说明P 是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针
    10 
    11 int  **p; //首先从P 开始,先与*结合,说是P 是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与int 结合,说明该指针所指向的元素是整型数据.由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针.
    12 
    13 int  p(int); //从P 处起,先与()结合,说明P是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数然后再与外面的int 结合,说明函数的返回值是一个整型数据
    14 
    15 int (*p)(int); //从P处开始,先与指针结合,说明P 是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P是一个指向有一个整型参数且返回类型为整型的函数的指针
    16 
    17 int *(*p(int))[3]; //可以先跳过,不看这个类型,过于复杂
    18 //从P 开始,先与()结合,说明P 是一个函数,然后进
    19 //入()里面,与int 结合,说明函数有一个整型变量
    20 //参数,然后再与外面的*结合,说明函数返回的是
    21 //一个指针,,然后到最外面一层,先与[]结合,说明
    22 //返回的指针指向的是一个数组,然后再与*结合,说
    23 //明数组里的元素是指针,然后再与int 结合,说明指
    24 //针指向的内容是整型数据.所以P 是一个参数为一个
    25 //整数据且返回一个指向由整型指针变量组成的数组
    26 //的指针变量的函数.

    备注:2012-12-31

    作者:kaizen
    声明:本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此声明,且在文章明显位置给出本文链接,否则保留追究法律责任的权利。
    签名:顺序 选择 循环
  • 相关阅读:
    SPOJ 1812 LCS2 后缀自动机
    [APIO2014]回文串 后缀自动机_Manancher_倍增
    SPOJ8222 NSUBSTR
    [HAOI2016]找相同字符 广义后缀自动机_统计出现次数
    洛谷 P3804 【模板】后缀自动机 统计单词出现次数
    洛谷 P1368 工艺 后缀自动机 求最小表示
    力扣题目汇总(反转字符串中的单词,EXCEL表列序号,旋置矩阵)
    力扣题目汇总(重复N次元素,反转字符串,斐波那契数)
    力扣题目汇总(机器人返回原点,按奇偶排序,数字的补数)
    博客园美化的第二天(动态设置,以及结合ps制作)
  • 原文地址:https://www.cnblogs.com/Braveliu/p/2840885.html
Copyright © 2011-2022 走看看