Thumbnail: cpp

array

by on under c++
5 minute read

初始化数组

  1. 数组的初始化不允许拷贝和赋值
  2. 字符数组初始化注意末尾空字符 \0

数组迭代器

指针也是迭代器

    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    int *p = arr;   // p 指向 arr 的第一个元素
    ++p;
    int *e = &arr[10]; //指向 arr 尾元素的下一个位置的指针

    for (int *b = arr; b != e; ++b)
        cout << *b << endl; //输出 arr 的元素

标准库函数 beginend

    int ia[] = {0,1,2,3,4,5,6,7,8,9};
    int *beg = begin(ia);   //指向 ia 首元素的指针
    int *last = end(ia);    //指向 arr 尾元素的下一个位置的指针

    while (beg != last && *beg >= 0)    //遍历 arr 直到找到第一个负数
        ++beg;

    int *b = arr, *e = arr + sz;    //sz 为数组长度, e 指向尾元素的下一个位置
    while (b < e) {
        ++b;
    } 

数组指针

    int ia[] = {0,2,4,6,8};
    int last = *(ia + 4);   //last = ia[4];
    last = *ia + 4;     //last = ia[0] + 4;

    int *p = &ia[2];
    int j = p[1];   //p[1] 等价于 *(p + 1), 就是 ia[3] 表示的那个元素
    int k = p[-2];  //p[-2] 是 ia[0] 表示的那个元素

混用 string 对象与 c 风格字符串

    string s("Hello world");
    char *str = s; //error
    const char *str = s.c_str(); //right

string.c_str() 返回一个指针,该指针指向一个以空字符结束的字符数组,这个数组所存的数据恰好与 string 的对象一样

使用数组初始化 vector 对象

    int int_arr[] = {0,1,2,3,4,5};
    vector<int> ivec(begin(int_arr), end(int_arr)); //ivec 有6个元素,为 int_arr 的副本

上述代码中,用于创建 ivec 的两个指针实际上指明了用来初始化的值在数组 int_arr 中的位置,其中第二个指针应指向待拷贝区域尾元素的下一个位置。
用于初始化 vector 对象的值也可以只是数组的一部分

 vector<int> subVec(int_arr + 1, int_arr + 4);

多维数组

多维数组的初始化

    int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
    int ia[3][4] ={ { 0 }, { 4 }, { 8 } };   //显式地初始化每行的首元素
    int ix[3][4] = {0, 3, 6, 9};            //显式地初始化第一行的 4 个元素

使用范围 for 语句处理多维数组

    size_t cnt = 0;
    for (auto &row : ia)        //对于外层数组地每一个元素
        for (auto &col : row){  //对于内层数组的每一个元素
        col = cnt;              //将下一个值赋给该元素
        ++cnt;
    }

上述代码为了改变数组中的元素所以采用了引用类型,但下述代码即使不改变元素也应当将外层循环设为引用类型

    for (const auto &row : ia) //对于外层数组地每一个元素
        for (auto col : row){  //对于内层数组的每一个元素
            cout<< col <<endl;

此处将外层循环控制变量声明成了引用类型,是为了避免数组被自动转成指针 若不设为引用类型,则会出现如下情况

    for (auto row : ia)
        for (auto col : row)

程序将无法通过编译,因为此时 row 地类型将被识别为 int* ,第二层循环将在这个指针内遍历,显然错误。

要使用范围 for 语句处理多维数组,除了最内层循环外,其他所有循环地控制变量都应该是引用类型。


指针和多维数组

p 是一个指向 4 个整数的数组的指针

    int ia[3][4];       //大小为 3 地数组,每个元素是含有 4 个整数的数组
    int (*p)[4] = ia;   //p 指向含有 4 个整数地数组
    p = &ia[2];         //p 指向 ia 的尾元素

    //注意括号
    int *ip[4];     //含有 4 个整型指针的数组
    int (*ip)[4];   //指向含有 4 个整数的数组

通过 auto 或者 decltype 避免在数组前加上指针类型

    //输出 ia 中每个元素的值,每个内层数组各占一行
    //p 指向含有 4 个整数的数组
    for (auto p = ia; p != ia + 3; ++p) {
        // q 指向含有 4 个整数数组的首元素, 也就是说,q 指向一个整数
        for (auto q = *p; q != *p + 4; ++q)
            cout << *p << ' ';
        cout << endl;
    }

    for (auto p =begin(ia); p != end(ia); ++p) {
        for (auto q = begin(*p); q != end(*p); ++q)
            cout << *q << ' ';
        cout << endl;
    }
c++