链表和二级指针的理解

       看上去这两个名词没有直接的联系,其实我只是突然想到这两个名词我之前的理解不够,想在此同时记录一下我对他们再次的理解,所以大家也不要纠结为什么把这两个技术点放在一起来解释。如果非要说这两个技术点的联系,那么就是实现链表功能会用到指针,但是好像是一级指针,并不会用到二级指针。

       其实作为一个做IT的开放人员来说,有时候你会发现你用代码实现了一个东西,但是你不知道为什么要这么用,这个代码的原理是什么,为什么要使用这种方法?其实到时候你会发现是你对这个事情的理解程度不够,它会让你对代码的理解更深,自己的认知也会提高,还有就是会给自己留下深刻的映象。就像我之前做过windows开发,用到C++,里面会用到STL的list vector,当时只知道能那么用,也知道这样用的好处是可以节约内存,但是后面慢慢发现这个技术方法背后的核心技术基础是用了链表,然后此时你就会发现你对链表,list和vector都有了深刻的认识,还大致知道他们之间的相互联系。

接下来我大致记录一下我自己对二级指针和链表的理解。

1、二级指针

二级指针顾名思义就是两次指针,什么意思呢,首先看一级指针:

int a = 100;

int *p = &a;

这个p就是一级指针,内存中a表示存储的变量数据,其值是100,这个数值存储的地方也有地址,就算不把a的地址赋值给p,这个地址也是存在的,这时p就表示一个内存地址,地址指向的a的地址

那么二级指针呢?

int **p2 = &p;

这个p2就是二级指针(这里只是举例子,在实际应用中一般不会这样用),p其实也是一个数值,只是这个数值是地址,然后对这个地址再取地址,并赋值给p2,就得到了一个二级指针

二级指针就是指针的指针,针对指针的指针一般用的很少,最近在做一个项目的时候发现有一种用法会用到二级指针,叙述如下:

项目是关于一个SDK,SDK里面有两个接口,一个是创建对象(指针对象),另一个是释放对象,然后在创建对象的时候SDK返回了一个指针对象,当用完之后需要释放这个对象,我们之前的方式是传入这个指针,进入函数,释放掉资源,并给指针赋值为NULL,最后发现外面的实参并没有赋值为NULL,此时就需要传这个对象的地址进去,其实传的就是二级指针(指针的指针),最后在里面释放对象并赋值对象为NULL,这样外面的实参也才会被赋值为null。可能还有其他用法,大家遇到的话欢迎评论交流。

2、链表

       链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,有一系列结点(地址)组成,结点可动态的生成。

        链表主要是便于管理长度或数量不确定的数据,相对于数组,链表处理这种数据时比较节省内存。动态语言通常不大需要链表,因为动态语言的解释器帮你管理内存,但当你对空间效率或插入动作的效率有特殊要求时也可在动态语言中使用链表。我大致说下为什么链表会比数组节约空间,是这样的,数组申请内存都是连续的内存,假如说你需要申请3M的数组,然后内存中有个连续的内存只有2M,然后JJ,这块剩余内存不行,必须找大于等于3M的内存空间地址,这样就导致2M的内存空间浪费,如果到时候其他地方又有剩余不足3M的空间,这样就会导致这种小空间越来越多,这个其实就是内存优化的问题,叫内存碎片化。但是如果此时使用链表的话就不存在这种情况,因为链表可以在不连续的内存空间实现数据的存储,所以链表可以减轻内存的碎片化。

2.1 具有这样的特点的数据可以用链表来保存:


    1,数据是逐渐增加的
    2,数据是不定长的,在存储第一个数据之前难以确定一个将来一共需要存储多少数据的上限,或者虽然可以确定上限,但这个上限又比通常大部分情况下数据可能达到的长度要大得多,因而一次性按照上限把空间分配好是不划算的。而链表则可以在每次需要增加新数据时才为之申请内存,不会造成浪费,也不会因一次申请不足而使数据的数量受到限制。
    3,不需要按照序号对数据进行随机访问。

    C++ STL 中提供了list容器,就是链表。同时STL还提供了vector容器,也可以用于处理具有上述特点的数据,而且vector还支持随机访问。

 2.2 链表的优缺点如下:

优点、链表实现数据元素储存的顺序储存,是连续的,内存地址不连续也可以,比数组更灵活。

缺点、因为含有大量的指针域,所以占用空间大,同时因为只有头结点(后面说明)是明确知道地址的,所以查找链表中的元素需要从头开始寻找,非常麻烦。

差不多总结完了,后面有新的理解再来更新,欢迎批评吐槽。

 

你可能感兴趣的:(C/C++,指针,链表,二级指针)