• 字符串和数组----数组


      和vector一样,数组的元素应为对象,因此不存在引用的数组。

    一、定义和初始化数组

    1、数组是一种复合类型。数组的声明形如a[d],其中a是数组的名字,d是数组的维度,维度说明了数组中元素的个数。编译的时候维度应该是已知的,因此维度必须是一个常量表达式。

    2、默认情况下,数组的元素被默认初始化。和内置类型的变量一样,如果在函数内部定义了某种内置类型的数组,那么默认初始化会令数组含有未定义的值。

    3、显示初始化数组元素

      可以对数组的元素进行列表初始化,此时允许忽略数组的维度。如果在声明时没有指明维度,编译器会根据初始值的数量计算并推测出来;相反,如果指明了维度,那么初始值的总数量不应超出指定的大小。如果维度比提供的初始值数量大,则用提供的初始值初始化靠前大的元素,剩下的元素执行值初始化

    1 int main()
    2 {
    3     const unsigned sz = 3;
    4     int a1[sz] = { 0, 1, 2 }; // 含有3个元素的数组,元素值分别是0,1,2
    5     int a2[] = { 0, 1, 2 }; // 维度是3的数组,元素值分别是0,1,2
    6     int a3[5] = { 0, 1, 2 }; // 维度是5的数组,元素值分别是0,1,2,0,0
    7     string a4[3] = { "hi", "bye" }; // 等价于a4[] = {"hi","bye",""}
    8     return 0;
    9 }

    4、字符数组的特殊性

      字符数组有一种额外的初始化形式,我们可以用字符串字面值对此类数组进行初始化。当使用这种方式时,一定要注意字符串字面值的结尾处还有一个空字符,这个空字符也会像字符串的其他字符一样被拷贝到字符数组中去。

    1 int main()
    2 {
    3 
    4     char a1[] = { 'c', '+', '+' }; // 列表初始化,没有空字符
    5     char a2[] = { 'c', '+', '+', '' }; // 列表初始化,含有显示的空字符
    6     char a3[] = "c++"; // 自动添加表示字符串结束的空字符
    7     //char a4[6] = "abcdef"; // 错误:没有空间来存放空字符,维度至少需要7
    8     return 0;
    9 }

     5、理解复杂的数组声明

      默认情况下,类型修饰符从右向左依次绑定。但要想理解数组声明的含义,最好的办法是从数组的名字开始按照由内向外的顺序阅读。

    1 int main()
    2 {
    3     int arr[10]; // 含有10个整数的数组
    4     int *ptrs[10]; // ptrs是一个含有10个整型指针的数组
    5     int(*Parray)[10] = &arr; // Parray是个指向大小为10的整型数组的指针
    6     int(&arrRef)[10] = arr; // arrRef是一个大小为10的整型数组的引用
    7     return 0;
    8 }

    二、指针和数组

    1、指针和数组名

      在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针。

      由上可知,在一些情况下数组的操作实际上是指针的操作,当使用数组作为一个auto变量的初始值时,推断得到的是指针而非数组。

    1 int main()
    2 {
    3     int a[] = { 1, 2, 3, 4, 5 }; // a 是一个含有5个整数的数组
    4     auto ca(a); // ca是一个整型指针,指向a的第一个元素
    5     //ca = 996; // 错误:ca是一个指针
    6     return 0;
    7 }

      当使用decltype时,上述转换不会发生,推断得到的仍然是相同维度的数组。

    1 int main()
    2 {
    3     int a[] = { 1, 2, 3, 4, 5 }; // a 是一个含有5个整数的数组
    4     decltype(a) ca; // ca 是一个含有5个整数的数组
    5     ca[0] = 996; // 把996赋给ca的第一个元素
    6     return 0;
    7 }

     2、数组的指针也是迭代器

      数组的指针比普通指针拥有更多功能。vector和string的迭代器支持的运算,数组的指针全都支持。

      c++11新标准引入了两个名为begin()和end()的函数,这两个函数的功能与容器中的两个同名成员函数功能类似,不过数组不是类类型,因此这两个函数不是成员函数。使用形式是把数组作为它们的参数,参数只能是数组名

    1 int main()
    2 {
    3     int a[] = { 1, 2, 3, 4, 5 }; // a是一个含有5个整数的数组
    4     int *s = std::begin(a);    // 指向a的首元素的指针
    5     int *e = std::end(a); // 指向a的尾元素的下一位置的指针
    6     return 0;
    7 }

     3、下标和指针

      如前所述,在很多情况下使用数组的名字其实用的是一个指向数组首元素的指针。一个典型的例子是当对数组使用下标运算符时,编译器会自动执行上述转换操作。只要指针指向的是数组的元素(或者数组中尾元素的下一位置),都可以执行下标运算。

    1 int main()
    2 {
    3     int a[] = { 1, 2, 3, 4, 5 }; // a是一个含有5个整数的数组
    4     int x = a[2]; // a转换成指向数组首元素的指针,a[2]得到(a+2)的元素
    5     int *p = &a[2]; // p指向索引为2的元素
    6     int j = p[1]; //p[1]等价于*(p+1),就是a[3]
    7     int k = p[-2]; // p[-2]等价于*(p-2),就是a[0]
    8     return 0;
    9 }

      虽然标准库类型string和vector也能执行下标运算,但是数组与它们相比还是有所不同。标准库类型限定使用的下标必须是无符号类型,而内置的下标运算无此要求。

  • 相关阅读:
    $P5240 Derivation$
    $P2504 [HAOI2006]聪明的猴子$
    $P1194 买礼物$
    $P2690 接苹果$
    $CF1141C Polycarp Restores Permutation$
    $CF1141B Maximal Continuous Rest$
    $CF1141A Game 23$
    $P1215 [USACO1.4]母亲的牛奶 Mother's Milk$
    $luogu2375[NOI2014]$
    poj 1419 (最大独立集)
  • 原文地址:https://www.cnblogs.com/ACGame/p/10061666.html
Copyright © 2020-2023  润新知