C++从零开始之指针及其语义和运用
为long(*)[4]的数字3060+sizeof(long[4])=3076,同理,*( *( *( b + 1 ) + 1 ) + 1 )返回long类型的地址类型的数字3076+sizeof(long)=3080,将5放在3080所标识的内存中。由前面对“[]”的说明可知*( *( *( b + 1 ) + 1 ) + 1 ) = 5;等效于b[1][1][1] = 5;,可如上自行推验。应注意虽然b是多维数组,但它仍是一块连续的内存空间。
为什么要有多级指针和多维数组?long a[3][4];和long a[12];都是分配一块连续的48字节内存空间,它们有什么区别?何时用前者何时用后者?在《C++从零开始》系列中强调要按语义编写程序,因此只要明确指针和数组的语义就能有条理地使用它们了。 数组的语义及运用——矢量和容器 一种类型,由几个相同类型的元素共同构成,这就是数组类型修饰符的语义。这正好可以用来映射线性代数中的矢量,如二维平面上的点坐标就是二维矢量。假设用double来记录点坐标的分量,则double a[2];就可以认为定义了一个二维点坐标,如果想要更具可读性,可typedef double POINT_2D[2]; POINT_2D a;。 实际中,很容易就发现数组其实实现了一个集合,即可用来作为容器以记录多个同一类型的数字。此时数组在类型上表现的语义——矢量——已被忽略,重点是定义出来的数组变量,即重点不再是POINT_2D,而是a.如:double container[300];就通过变量名而不再是类型来体现语义了。作为容器光写个double container[300];是不够的,因为无法知道哪些元素有效哪些无效,因此还需其它的变量介入以共同完成一个容器的基本功能。对此,实际中常编写一个类来隐藏上面实现容器的基本功能的细节,这个类映射的语义是容器,这种类一般被称作容器类或集合类,如STL中的容器类vector.这种类也被称作是对数组container的封装类。 那多维数组的语义是什么?有何意义?这其实很简单,因为数组是类型修饰符,不用去管它一维还是多维,只用知道它是多个原类型的元素构成的一个类型。比如long a[2][3];就可以映射为一个二维矢量,只不过每个分量又是一个三维矢量罢了,这正好可映射线性代数中的矩阵。因此typedef MATRIX_23[2][3]; MATRIX_23 a;。同理可只注重定义的数组变量而忽略其类型所表征的语义,如double a[300][300];。这里的a和double b[90000];定义的b有什么区别?最终所操作的内存没有区别,仅仅语义上的差别——前者所代表的容器需要两个关键字(key)才能定位一个元素(value),而后者只用一个关键字就可以定位元素(a[2][3] = 3;等同于b[603] = 3;,但前者效率更低)。前者如电子表格中的表格,给出横纵两个坐标才能定位欲写入数据的位置;后者则是一般的连续容器。还可以既注重数组的类型语义——矢量,又注重数组的实例语义——容器,如:POINT_2D PContainer[300];,PContainer的类型实际是double[300][2]. 引用和间接 欲说明指针的语义及其运用,最好是先了解一下引用和间接。这里的引用不是指C++中的引用类型修饰符“&”,而是一个语言无关的概念,在《C++从零开始(八)》中已详细阐明,在此再说明一下:引用表示了一个连接关系,以至于原来需要某种手段才能达到的目的,现在另一种手段也能达到,这种手段往往比原来的手段在某方面有优势。如某人的手机号码就是和某人谈话的引用;图书馆里藏书的编号就是书的引用;某人的名字就是某人的引用。引用有什么用?其本身是没用的,一定有一些手段来实现其“相当于”的目的。如某人的手机没带或没电,则“手机号码”无法完成相当于“和某人谈话”的功能;没有正确的排放书籍,书的编号毫无意义;没有完备的搜查系统,给出人 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |