企业网站建设招标书,网站建设新的技术方案,网站代码怎么看,电商培训机构有哪些哪家比较好3.5数组
数组是一种类似于标准库类型vector#xff08;参见3.3节#xff0c;第86页#xff09;的数据结构#xff0c;但是在性能和灵活性的权衡上又与vector有所不同。与vector相似的地方是#xff0c;数组也是存放类型相同的对象的容器#xff0c;这些对象本身没有名字…3.5数组
数组是一种类似于标准库类型vector参见3.3节第86页的数据结构但是在性能和灵活性的权衡上又与vector有所不同。与vector相似的地方是数组也是存放类型相同的对象的容器这些对象本身没有名字需要通过其所在位置访问。与vector不同的地方是数组的大小确定不变不能随意向数组中增加元素。因为数组的大小固定,因此对某些特殊的应用来说程序的运行时性能较好但是相应地也损失了一些灵活性。如果不清楚元素的确切个薮请使用vector
3.5.1定义和初始化内置数组
数组是一种复合类型参见2.3节第45页。数组的声明形如a[d],其中a是数组的名字d是数组的维度。维度说明了数组中元素的个数因此必须大于0。数组中元素的个数也属于数组类型的一部分编译的时候维度应该是已知的。也就是说维度必须是一个常量表达式参见2.4.4节第58页和内置类型的变量一样如果在函数内部定义了某种内置类型的数组那么默认初始化会令数组含有未定义的值定义数组的时候必须指定数组的类型不允许用auto。关键字由初始值的列表推断类型。另外和vector一样数组的元素应为对象因此不存在引用的数组
显式初始化数组元素
可以对数组的元素进行列表初始化(参见3.3.1节第88页)此时允许忽略数组的维度。如果在声明时没有指明维度编译器会根据初始值的数量计算并推测出来相反如果指明了维度那么初始值的总数量不应该超出指定的大小。如果维度比提供的初始值数量大则用提供的初始值初始化靠前的元素剩下的元素被初始化成默认值(参见3.3.1节第88页)字符数组的特殊性
字符数组有一种额外的初始化形式我们可以用字符串字面值(参见2.1.3节第36页)对此类数组初始化。当使用这种方式时一定要注意字符串字面值的结尾处还有一个空字符这个空字符也会像字符串的其他字符一样被拷贝到字符数组中去al的维度是3,a2和a3的维度都是4,a4的定义是错误的。尽管字符串字面值Daniel1看起来只有6个字符但是数组的大小必须至少是7,其中6个位置存放字面值的内容另外1个存放结尾处的空字符。理解复杂的数组声明
和vector-样数组能存放大多数类型的对象。例如可以定义一个存放指针的数组。又因为数组本身就是对象所以允许定义数组的指针及数组的引用。在这几种情况中定义存放指针的数组比较简单和直接但是定义数组的指针或数组的引用就稍微复杂一点了:默认情况下类型修饰符从右向左依次绑定。对于Ptrs来说从右向左(参见2.3.3节,第52页)理解其含义比较简单首先知道我们定义的是一个大小为10的数组它的名字是ptrs,然后知道数组中存放的是指向int的指针。但是对于Parray来说从右向左理解就不太合理了。因为数组的维度是紧跟着被声明的名字的所以就数组而言由内向外阅读要比从右向左好多了。由内向外的顺序可帮助我们更好地理解Parray的含义首先是圆括号括起来的部分*Parray意味着Parray是个指针接下来观察右边可知道Parray是个指向大小为10的数组的指针最后观察左边知道数组中的元素是int。这样最终的含义就明白无误了Parray是一个指针它指向一个int数组数组中包含10个元素。同S,(arrRef)表示arrRef是一个引用它引用的对象是一个大小为10的数组数组中元素的类型是int。当然对修饰符的数量并没有特殊限制in t * (arry) [10] p tr s ; / / a r r y 是数组的引用该 数 组含有 1 0 个指针按照由内向外的顺序阅读上述语句首先知道arry是一个引用然后观察右边知道,arry引用的对象是一个大小为10的数组最后观察左边知道数组的元素类型是指向int的指针。这样arry就是一个含有10个int型指针的数组的引用要想理解数组声明的含义最好的办法是从数组的名字开始按照由内向外的顺序阅读
3 .5 .2 访问数组元素
与标准库类型vector和string一样数组的元素也能使用范围for语句或下标运算符来访问。数组的索引从0开始以一个包含10个元素的数组为例它的索引从0到9,而非从1到10。在使用数组下标的时候通常将其定义为size_t类型。size_t是一种机器相关的无符号类型它被设计得足够大以便能表示内存中任意对象的大小。在cstdef头文件中定义了sizet类型这个文件是C标准库stddef.h头文件的C语言版本。3 .5 .3 指针和数组
在C语言中指针和数组有非常紧密的联系。就如即将介绍的使用数组的时候编译器一般会把它转换成指针。通常情况下使用取地址符参见2.3.2节第47页来获取指向某个对象的指针取地址符可以用于任何对象。数组的元素也是对象对数组使用下标运算符得到该数组指定位置的元素。因此像其他对象一样对数组的元素使用取地址符就能得到指向该元素的指针string nums [] {one” two, *threen ; // 数组的元素是 string 对象string *p nums [0] ; // p 指向 nums 的第一个元素然而数组还有一个特性在很多用到数组名字的地方编译器都会自动地将其替换为一个指向数组首元素的指针string *p2 nums; // 等价于 p2 nums [0]在大多数表达式中使用数组类型的对象其实是使用一个指向该数组首元素的指针。由上可知在一些情况下数组的操作实际上是指针的操作这一结论有很多隐含的意思。其中一层意思是当使用数组作为一个auto 参见2.5.2节第 61页变量的初始值 时推断得到的类型是指针而非数组指针也是迭代器
与2.3.2节第47页介绍的内容相比指向数组元素的指针拥有更多功能。vector和string的迭代器参见3.4节第95页支持的运算数组的指针全都支持。例如允许使用递增运算符将指向数组元素的指针向前移动到下一个位置上int arr[] 10,1,2,3,4,5,6,7,8,9};int *p arr; // p 指 向 arr的第一个元素p // p 指向 arr [1]就像使用迭代器遍历vector对象中的元素一样使用指针也能遍历数组中的元素。当然这样做的前提是先得获取到指向数组第一个元素的指针和指向数组尾元素的下一位置的指针。之前已经介绍过通过数组名字或者数组中首元素的地址都能得到指向首元素的指针不过获取尾后指针就要用到数组的另外一个特殊性质了。我们可以设法获取数组尾元素之后的那个并不存在的元素的地址in t *e arr [10] ; / / 指向a r r 尾元素的下一位置的指针这里显然使用下标运算符索引了一个不存在的元素arr有 10个元素尾元素所在位置的索引是9 , 接下来那个不存在的元素唯一的用处就是提供其地址用于初始化e , 就像尾后迭代器(参见3.4.1节第 95页)一样尾后指针也不指向具体的元素。因此不能对尾后指针执行解引用或递增的操作。利用上面得到的指针能重写之前的循环令其输出arr的全部元素for ( int *b arr ; b ! e ; b) cout « *b « endl; // 输出 arr 的元素
标准库函数begin和end
尽管能计算得到尾后指针但这种用法极易出错。为了让指针的使用更简单、更安全C11新标准引入了两个名为begin和end的函数。这两个函数与容器中的两个同名成员(参见3.4.1节第95页)功能类似不过数组毕竟不是类类型因此这两个函数不是成员函数。正确的使用形式是将数组作为它们的参数begin函数返回指向ia首元素的指针end函数返回指向ia尾元素下一位置的指针这两个函数定义在iterator头文件中。使用begin和end可以很容易地写出一个循环并处理数组中的元素。例如假设arr是一个整型数组下面的程序负责找到arr中的第一个负数首先定义了两个名为pbeg和pend的整型指针其中pbeg指向arr的第一个元素,pend指向arr尾元素的下一位置。while语句的条件部分通过比较pbeg和pend来确保可以安全地对pbeg解引用如果pbeg确实指向了一个元素将其解引用并检查元素值是否为负值。如果是条件失效、退出循环如果不是将指针向前移动一位继续考查下一个元素。一个指针如果指向了某种内置类型数组的尾元素的“下一位置”则其具备与ivector的end函数返回的与迭代器类似的功能。特别要注意尾后指针不能执行解引用和递增操作,
指针运算
指向数组元素的指针可以执行表3.6 (第96页 )和 表 3.7 (第 99页)列出的所有迭代器运算。这些运算包括解引用、递增、比较、与整数相加、两个指针相减等用在指针和用在迭代器上意义完全一致。给(从)一个指针加上(减去)某整数值结果仍是指针。新指针指向的元素与原来的指针相比前进了(后退了)该整数值个位置ip加上4所得的结果仍是一个指针该指针所指的元素与ip原来所指的元素相比前进了 4个位置。给指针加上一个整数得到的新指针仍需指向同一数组的其他元素或者指向同一数组的尾元素的下一位置/ / 正确arr转换成指向它首元素的指针p 指向arr尾元素的下一位置int *p arr sz; / / 使用警告不要解引用int *p2 arr 10; / / 错误arr只 有 5 个元素p2的值未定义当给arr加上sz时编译器自动地将arr转换成指向数组arr中首元素的指针。执行加法后指针从首元素开始向前移动了sz(这里是5)个位置指向新位置的元素。也就是说它指向了数组arr尾元素的下一位置。如果计算所得的指针超出了上述范围就将产生错误而且这种错误编译器一般发现不了。和迭代器一样两个指针相减的结果是它们之间的距离。参与运算的两个指针必须指向同一个数组当中的元素auto nend(arr)-begin(arr);//n的值是5,也就是arr中元素的数量两个指针相减的结果的类型是一种名为ptrdiff_t的标准库类型和size_t一样ptrdiff_t也是一种定义在cstddef头文件中的机器相关的类型。因为差值可能为负值所以ptrdiff_t是一种带符号类型。只要两个指针指向同一个数组的元素或者指向该数组的尾元素的下一位置就能利用关系运算符对其进行比较。例如可以按照如下的方式遍历数组中的元素尽管作用可能不是特别明显但必须说明的是上述指针运算同样适用于空指针(参见2.3.2节第48页)和所指对象并非数组的指针。在后一种情况下两个指针必须指向同一个对象或该对象的下一位置。如果p是空指针允许给p加上或减去一个值为0的整型常量表达式(参见2.4.4节第58页)。两个空指针也允许彼此相减结果当然是0。
解引用和指针运算的交互
指针加上一个整数所得的结果还是一个指针。假设结果指针指向了一个元素则允许解引用该结果指针int ia[] 0,2,4,6,8}; / / 含 有 5个整数的数组int last * ia 4 ; / / 正确把 last初始化成8,也 就 是 ia [4]的值表达式*ia4计算ia前进4个元素后的新地址解引用该结果指针的效果等价于表达式 ia[4]回忆一下在3.4.1节 第98页中介绍过如果表达式含有解引用运算符和点运算符最好在必要的地方加上圆括号。类似的此例中指针加法的圆括号也不可缺少。如果写成下面的形式last *ia 4; // 正确 last 4 等价于 ia [0] 4含义就与之前完全不同了此时先解引用ia,然后给解引用的结果再加上4。4.1.2节 第 121页将对这一问题做进一步分析。虽然标准库类型string和vector也能执行下标运算但是数组与它们相比还是有所不同。标准库类型限定使用的下标必须是无符号类型而内置的下标运算无此要求上面的最后一个例子很好地说明了这一点。内置的下标运算符可以处理负值当然结果地址必须指向原来的指针所指同一数组中的元素或是同一数组尾元素的下一位置。内置的下标运算符所用的索引值不是无符号类型这一点与vector和string 不一样。
3.5.4 C 风格字符串
字符串字面值是一种通用结构的实例这种结构即是C由C继承而来的C风格字符串(C-stylecharacterstring)oC风格字符串不是一种类型而是为了表达和使用字符串而形成的一种约定俗成的写法。按此习惯书写的字符串存放在字符数组中并以空字符结束。以空字符结束的意思是在字符串最后一个字符后面跟着一个空字符。一般利用指针来操作这些字符串。
C标准库String函数
表 3.8列举了 C 语言标准库提供的一组函数这些函数可用于操作C 风格字符串它们定义在cstring头文件中cstring是 C 语言头文件string.h 的 C版本表 3.8所列的函数不负责验证其字符串参数:传入此类函数的指针必须指向以空字符作为结束的数组不遇到 \0 不结束比较字符串
比较两个C风格字符串的方法和之前学习过的比较标准库string对象的方法大相径庭。比较标准库string对象的时候用的是普通的关系运算符和相等性运算符谨记之前介绍过的当使用数组的时候其实真正用的是指向数组首元素的指针(参见3.5.3节第 105页)。因此上面的if 条件实际上比较的是两个const char*的值。这两个指针指向的并非同一对象所以将得到未定义的结果。比较两个C风格字符串需要调用strcmp函数此时比较的就不再是指针了。如果两个字符串相等strcmp返回0如果前面的字符串较大返回正值如果后面的字符串较大返回负值if (strcmp (cal, ca2) 0) // 和两个 string 对象的比较 si s2 效果一样-个潜在的问题是我们在估算largeStr所需的空间时不容易估准而且largeStr所存的内容一旦改变就必须重新检查其空间是否足够。不幸的是这样的代码到处都是,程序员根本没法照顾周全。这类代码充满了风险而且经常导致严重的安全泄漏。对大多数应用来说使用标准库string要比使用C 风格字符串更安全、更高效
3.5.5与旧代码的接口
很多C程序在标准库出现之前就已经写成了它们肯定没用到string和vector类型。而且有一些C程序实际上是与C语言或其他语言的接口程序当然也无法使用C标准库。因此现代的C程序不得不与那些充满了数组和/或C风格字符串的代码衔接为了使这一工作简单易行C专门提供了一组功能。
混用string对象和C风格字符串
3.2.1节(第76页)介绍过允许使用字符串字面值来初始化string对象string s (Hello World) ; // s 的内容是 Hello World更一般的情况是任何出现字符串字面值的地方都可以用以空字符结束的字符数组来替代允许使用以空字符结束的字符数组来初始化string对象或为string对象赋值。在string对象的加法运算中允许使用以空字符结束的字符数组作为其中一个运算对象(不能两个运算对象都是)在string对象的复合赋值运算中允许使用以空字符结束的字符数组作为右侧的运算对象。上述性质反过来就不成立了如果程序的某处需要一个C风格字符串无法直接用string对象来代替它。例如不能用string对象直接初始化指向字符的指针。为了完成该功能string专门提供了一个名为c_str的成员函数char* strs;//错误不能用string对象初始化char*const char* strs.cstr();//正确 顾名思义c_str函数的返回值是一个C风格的字符串。也就是说函数的返回结果是一个指针该指针指向一个以空字符结束的字符数组而这个数组所存的数据恰好与那个string对象的一样。结果指针的类型是const char*,从而确保我们不会改变字符数组的内容。我们无法保证c_str函数返回的数组一直有效事实上如果后续的操作改变了 s 的值就可能让之前返向的数组失去效用。如果执行完c_str ()函数后程序想一直都能使用其返回的数组最好将该数 组重新拷贝一份
使用数组初始化vector对象
3.5.1节(第102页)介绍过不允许使用一个数组为另一个内置类型的数组赋初值也不允许使用vector对象初始化数组。相反的允许使用数组来初始化vector对象。要实现这一目的只需指明要拷贝区域的首元素地址和尾后地址就可以了在上述代码中用于创建ivec的两个指针实际上指明了用来初始化的值在数组int_arr中的位置其中第二个指针应指向待拷贝区域尾元素的下一位置。此例中使用标准库函数begin和end(参见3.5.3节第106页)来分别计算int_arr的首指针和尾后指针。在最终的结果中ivec将包含6个元素它们的次序和值与数组int arr完全相同3.6多维数组
严格来说C语言中没有多维数组通常所说的多维数组其实是数组的数组。谨记这一点对今后理解和使用多维数组大有益处。当一个数组的元素仍然是数组时通常使用两个维度来定义它一个维度表示数组本身大小另外-个维度表示其元素(也是数组)大小如3.5.1节(第103页)所介绍的按照由内而外的顺序阅读此类定义有助于更好地理解其真实含义。在第一条语句中我们定义的名字是ia,显然ia是一个含有3个元素的数组。接着观察右边发现ia的元素也有自己的维度所以ia的元素本身又都是含有4个元素的数组。再观察左边知道真正存储的元素是整数。因此最后可以明确第一条语句的含义它定义了一个大小为3的数组该数组的每个元素都是含有4个整数的数组。使用同样的方式理解arr的定义。首先arr是一个大小为10的数组它的每个元素都是大小为20的数组这些数组的元素又都是含有30个整数的数组。实际上定义数组时对下标运算符的数量并没有限制因此只要愿意就可以定义这样一个数组它的元素还是数组下一级数组的元素还是数组再下一级数组的元素还是数组以此类推。对于二维数组来说常把第一个维度称作行第二个维度称作列。多维数组的下标引用
可以使用下标运算符来访问多维数组的元素此时数组的每个维度对应一个下标运算符。如果表达式含有的下标运算符数量和数组的维度一样多该表达式的结果将是给定类型的元素反之如果表达式含有的下标运算符数量比数组的维度小则表达式的结果将是给定索引处的一个内层数组在第一个例子中对于用到的两个数组来说表达式提供的下标运算符数量都和它们各自的维度相同。在等号左侧ia[2]得到数组ia的最后一行此时返回的是表示ia最后一行的那个一维数组而非任何实际元素对这个一维数组再取下标得到编号为[3]的元素也就是这一行的最后一个元素。类似的等号右侧的运算对象包含3个维度。首先通过索引0得到最外层的数组它是一个大小为20的(多维)数组接着获取这20个元素数组的第一个元素得到一个大小为30的一维数组最后再取出其中的第一个元素。在第二个例子中把row定义成一个含有4个整数的数组的引用然后将其绑定到ia的第2行。再举一个例子程序中经常会用到两层嵌套的for循环来处理多维数组的元素constexpr size_t rowCnt 3, colCnt 4;外层的for循环遍历ia的所有元素注意这里的元素是一维数组内层的for循环则遍历那些一维数组的整数元素。此例中我们将元素的值设为该元素在整个数组中的序号。指针和多维数组
当程序使用多维数组的名字时也会自动将其转换成指向数组首元素的指针。定义指向多维数蛆的指针时千万别忘了这个多维数组实际上是数组的数组因为多维数组实际上是数组的数组所以由多维数组名转换得来的指针实际上是指向第一个内层数组的指针:根据3.5.1节 (第 103页)提出的策略我们首先明确(*p)意味着p 是一个指针。接着观 察右边发现指针P 所指的是一个维度为4 的数组再观察左边知道数组中的元素是整数。因此p 就是指向含有4个整数的数组的指针。外层的for循环首先声明一个指针p并令其指向ia的第一个内层数组然后依次迭代直到ia的全部3行都处理完为止。其中递增运算p负责将指针p移动到ia的下一行。内层的for循环负责输出内层数组所包含的值。它首先令指针q指向p当前所在行的第一个元素。*p是一个含有4个整数的数组像往常一样数组名被自动地转换成指向该数组首元素的指针。内层for循环不断迭代直到我们处理完了当前内层数组的所有元素为止。为了获取内层for循环的终止条件再一次解引用p得到指向内层数组首元素的指针给它加上4就得到了终止条件。当然使用标准库函数begin和end(参见3.5.3节第106页)也能实现同样的功能而且看起来更简洁一些在这一版本的程序中循环终止条件由end函数负责判断。虽然我们也能推断出p的类型是指向含有4个整数的数组的指针q的类型是指向整数的指针但是使用auto。关键字我们就不必再烦心这些类型到底是什么了小结
string和vector是两种最重要的标准库类型。string对象是一个可变长的字符序列vector对象是一组同类型对象的容器。迭代器允许对容器中的对象进行间接访问对于string对象和vector对象来说可以通过迭代器访问元素或者在元素间移动。数组和指向数组元素的指针在一个较低的层次上实现了与标准库类型string和vector类似的功能。一般来说应该优先选用标准库提供的类型之后再考虑C语言内置的低层的替代品数组或指针。
术语表
begin是string和vector的成员返回指向第一个元素的迭代器。也是一个标准库函数输入一个数组返回指向该数组首元素的指针。缓冲区溢出(bufferoverflow)一种严重的程序故障主要的原因是试图通过一个越界的索引访问容器内容容器类型包括string、vector和数组等。C风格字符串(C-stylestring)以空字符结束的字符数组。字符串字面值是C风格字符串C风格字符串容易出错。类模板用于创建具体类类型的模板。要想使用类模板必须提供关于类型的辅助信息。例如要定义一个vector对象需要指定元素的类型vectorint包含int类型的元素。编译器扩展(compilerextension)某个特定的编译器为C语言额外增加的特性。基于编译器扩展编写的程序不易移植到其他编译器上。容器(container)是一种类型其对象容纳了一组给定类型的对象。vector是一种容器类型。拷贝初始化(copyinitialization)使用赋值号()的初始化形式。新创建的对象是初始值的一个副本。difference_type由string和vector定义的一种带符号整数类型表示两个迭代器之间的距离。直接初始化(directinitialization)不使用赋值号()的初始化形式。empty是string和vector的成员返回一个布尔值。当对象的大小为0时返回真否则返回假.end是string和vector的成员返回一个尾后迭代器。也是一个标准库函数输入一个数组返回指向该数组尾元素的下-位置的指针。getline在string头文件中定义的一个函数以一个istream对象利--个string对象为输入参数。该函数首先读取输入流的内容直到遇到换行符停止然后将读入的数据存入string对象最后返回istream对象。其中换行符读入但是不保留。索引(index)是下标运算符使用的值。表示要在string对象、vector对象或者数组中访问的一个位置。实例化(instantiation)编译器生成一个指定的模板类或函数的过程。迭代器(iterator)是一种类型用于访问容器中的元素或者在元素之间移动。迭代器运算(iteratorarithmetic)是string或vector的迭代器的运算迭代器与整数相加或相减得到一个新的迭代器与原来的迭代器相比新迭代器向前或向后移动了若干个位置。两个迭代器相减得到它们之间的距离此时它们必须指向同一个容器的元素或该容器尾元素的下一位置。以空字符结束的字符串(null-terminatedstring)是一个字符串它的最后一个字符后而还跟着一个空字符(\0)。尾后迭代器(off-the-enditerator)end函数返I可的迭代器指向一个并不存在的元素该元素位于容器尾元素的下一位置。指针运算(pointerarithmetic)是指针类型支持的算术运算。指向数组的指针所支持的运算种类与迭代器近算一样。prtdiff_t是cstddef头文件中定义的一种与机器实现有关的带符号整数类型它的空间足够大能够表示数组中任意两个指针之间的距离。pushback是vector的成员向vector对象的木尾添加元素。范围for语句(rangefor)-种控制语句可以在值的一个特定集合内迭代。size是string和vector的成员分别返回字符的数量或元素的数量。返回值的类型是size_type。size_t是cstddef头文件中定义的一种与机器实现有关的无符号整数类型它的空间足够大能够表示任意数组的大小。size_type是string和vector定义的类型的名字能存放下任意string对象或vector对象的大小。在标准中size_type被定义为无符号类型。string是一种标准库类型表示字符的序列。using声明(usingdeclaration)令命名空间中的某个名字可被程序直接使用。using命名空间::名字L述语句的作用是令程序可以直接使用名字,而无须写它的前缀部分命名空间值初始化(valueinitialization)是一种初始化过程。内置类型初始化为0,类类型由类的默认构造函数初始化。只有当类包含默认构造函数时该类的对象才会被值初始化。对于容器的初始化来说如果只说明了容器的大小而没有指定初始值的话就会执行值初始化。此时编译器会生成一个值而容器的元素被初始化为该值。vector是-种标准库类型容纳某指定类型的一组元素。运算符(operator)是迭代器和指针定义的递增运算符。执行“加1”操作使得迭代器指向下一个元素[]运算符([]operator)下标运算符Oobj[j]得到容器对象。bj中位置j的那个元素。索引从0开始第一个元素的索引是0,尾元素的索引是。bj.size()-1.下标运算符的返回值是一个对象。如果p是指针、n是整数则p[n]与*(pn)等价。-运算符(-operator)箭头运算符该运算符综合了解引用操作和点操作.a-b等价于(*a).b。运算符(《operator)标准库类型string定义的输出运算符负责输出string对象中的字符。运算符(operator)标准库类型string定义的输入运算符负责读入一组字符遇到空白停止读入的内容赋给运算符右侧的运算对象该运算对象应该是一个string对象。!运算符^operator)逻辑非运算符将它的运算对象的布尔值取反。如果运算对象是假则结果为真如果运算对象是真:则结果为假。运算符(operator)逻辑与运算符如果两个运算对象都是真结果为真。只有当左侧运算对象为真时才会检查右侧运算对象。II运算符(||operator)逻辑或运算符任何一个运算对象是真结果就为真。只有里左侧运算对象为假时才会检查右侧运算对象。